(注:寫這篇文章,我找到了解決辦法,這似乎在這篇文章的附錄)
要重現該問題,您需要所需的滾動條。 (這就是爲什麼有些人在重現這個bug方面有困難。)這意味着顯而易見的解決方法是讓您的水平滾動條成爲可選項。 (這並不總是實用。)
當您將窗口的寬度拖出超過1200像素左右時,您只會看到該錯誤。在此之前,滾動條會正常工作。
而這個問題只出現在Nimbus中。 (它可能出現在SynthLookAndFeel創建的其他L & F中,但我還沒有調查過。)
我發現虛假滾動條的拇指只顯示在您不需要滾動時,所以它只是一個視覺錯誤。當你需要滾動時,滾動條的大拇指會出現並能正常工作,雖然它可能不是合適的尺寸。這可能是它尚未修復的原因。
下面是一個例子,您可以比較不同的L & F。在本例中,選擇Nimbus,然後向內拖動寬度並觀察滾動條大小如何變化。當您比背景圖像更寬時,虛假滾動條將會顯示。一旦變窄,就會出現一個有效的滾動條大拇指,但它會有點過小。當你變小時,滾動條的大拇指會保持一個不變的大小,直到達到某個點(視口寬度爲1282像素),那麼它會開始變小,就像它應該的那樣。
隨着任何其他L & F,只要你比背景圖像窄,拇指會出現,幾乎填滿其空間。隨着窗戶變小,它變得越來越小,就像它應該的那樣。
通過使圖標更小(這一鍛鍊還可將揭示雨雲如何繪製比任何其它L. & F.要慢得多)
你可以觀察不同,但仍是不正確的行爲。嘗試800 X 450時,視口寬度爲> 1035將出現雜散滾動條
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* NimbusScrollBug
* <p/>
* @author Miguel Muñoz
*/
public class NimbusScrollBug extends JPanel {
private static final long serialVersionUID = -4235866781219951631L;
private static JFrame frame;
private static boolean firstTime = true;
private static Point location;
private static final UIManager.LookAndFeelInfo[] INFOS
= UIManager.getInstalledLookAndFeels();
private final JLabel viewPortLabel = new JLabel();
public static void main(final String[] args) {
makeMainFrame(new NimbusScrollBug(), "System");
}
public static void makeMainFrame(final NimbusScrollBug mainPanel,
final String name) {
if (firstTime) {
installLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
frame = new JFrame(name);
final Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(mainPanel, BorderLayout.CENTER);
contentPane.add(makeButtonPane(mainPanel), BorderLayout.LINE_START);
frame.setLocationByPlatform(firstTime);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setVisible(true);
if (firstTime) {
location = frame.getLocation();
} else {
frame.setLocation(location);
}
frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentMoved(final ComponentEvent e) {
location = e.getComponent().getLocation();
}
});
firstTime = false;
}
private static JPanel makeButtonPane(final NimbusScrollBug mainPanel) {
JPanel innerButtonPanel = new JPanel(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0; // forces vertical layout.
for (final UIManager.LookAndFeelInfo lAndF : INFOS) {
final JButton button = new JButton(lAndF.getName());
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
frame.dispose();
installLookAndFeel(lAndF.getClassName());
makeMainFrame(new NimbusScrollBug(), lAndF.getName());
}
});
innerButtonPanel.add(button, constraints);
}
final String version = System.getProperty("java.version");
JLabel versionLabel = new JLabel("Java Version " + version);
innerButtonPanel.add(versionLabel, constraints);
JPanel outerButtonPanel = new JPanel(new BorderLayout());
outerButtonPanel.add(innerButtonPanel, BorderLayout.PAGE_START);
return outerButtonPanel;
}
private static void installLookAndFeel(final String className) {
//noinspection OverlyBroadCatchBlock
try {
UIManager.setLookAndFeel(className);
} catch (Exception e) {
//noinspection ProhibitedExceptionThrown
throw new RuntimeException(e);
}
}
private NimbusScrollBug() {
Icon icon = new Icon() {
@Override
public void paintIcon(final Component c, final Graphics g,
final int x, final int y) {
Graphics2D g2 = (Graphics2D) g;
g2.translate(x, y);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Stroke lineStroke = new BasicStroke(6.0f);
g2.setStroke(lineStroke);
g2.setColor(Color.white);
g2.fillRect(0, 0, getIconWidth(), getIconHeight());
g2.setColor(Color.RED);
g2.drawLine(0, 0, getIconWidth(), getIconHeight());
g2.drawLine(0, getIconHeight(), getIconWidth(), 0);
g2.dispose();
}
@Override
public int getIconWidth() {
return 1600;
}
@Override
public int getIconHeight() {
return 900;
}
};
JLabel label = new JLabel(icon);
setLayout(new BorderLayout());
final JScrollPane scrollPane = new JScrollPane(label,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
label.addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
@Override
public void ancestorResized(final HierarchyEvent e) {
viewPortLabel.setText("ViewPort Size: "
+ scrollPane.getViewport().getSize());
}
});
add(scrollPane, BorderLayout.CENTER);
add(viewPortLabel, BorderLayout.PAGE_END);
}
}
附錄(視域大小在所述窗口的底部示出。):進一步調查顯示的問題。該NimbusDefaults類,這對於雨雲創建UIDefaults的情況下,有這樣一行:
d.put("ScrollBar.maximumThumbSize", new DimensionUIResource(1000, 1000));
任何其他外觀採用4096的兩個值(所以,對於真正的大顯示器,他們會表現出相同的行爲)。
下面的方法,可用於安裝任何的外觀和感覺,將解決這個問題:
private static void installLookAndFeel(final String className) {
//noinspection OverlyBroadCatchBlock
try {
Class<?> lnfClass = Class.forName(className, true,
Thread.currentThread().getContextClassLoader());
final LookAndFeel lAndF;
lAndF = (LookAndFeel) lnfClass.getConstructor().newInstance();
// Reset the defaults after instantiating, but before
// calling UIManager.setLookAndFeel(). This fixes the Nimbus bug
DimensionUIResource dim = new DimensionUIResource(4096, 4096);
lAndF.getDefaults().put("ScrollBar.maximumThumbSize", dim);
UIManager.setLookAndFeel(lAndF);
} catch (Exception e) {
final String systemName = UIManager.getSystemLookAndFeelClassName();
// Prevents an infinite recursion that's not very likely...
// (I like to code defensively)
if (!className.equals(systemName)) {
installLookAndFeel(systemName);
} else {
// Feel free to handle this any other way.
//noinspection ProhibitedExceptionThrown
throw new RuntimeException(e);
}
}
}
當然,你也可以解決該問題通過使用一個更大的價值非常大的顯示器。
我確認垂直滾動條有完全相同的問題,但只有當窗口垂直方向變得很大時纔會出現。這就是爲什麼這個問題通常只能在水平滾動條上看到的原因。
呵呵。不,我無法使用此代碼重現此問題。我不得不添加一堆列,以便JTable從面板延伸出來。當我這樣做,它正確滾動。我會繼續玩。另外,請參閱我的第二次編輯..我應該在之前提到它。 – 2012-07-16 20:13:29
好的,我有你的代碼去做。添加足夠多的列,以便行橫向伸出滾動窗格,並添加足夠的行,以便它也垂直伸展。我做到了,現在它只會垂直滾動。 – 2012-07-16 22:45:15