如果我运行以下示例,我会在JSplitPane的右侧闪烁。有没有办法避免这种情况?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class FlickerTest
{
int width = 1;
private void create()
{
final JFrame f = new JFrame("JSplitPane");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p1 = new JPanel();
p1.setPreferredSize(new Dimension(100, 300));
JPanel p2 = new JPanel();
p2.setPreferredSize(new Dimension(0,0));
p2.setBackground(Color.gray);
JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, p1, p2);
jsp.setSize(new Dimension(400, 800));
Timer timer = new Timer(1, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
width++;
if (width == 2)
{
try
{
Thread.sleep(1500);
}
catch (Exception ex)
{
}
}
int frameWidth = f.getWidth() + width;
Dimension d = new Dimension(frameWidth, f.getHeight());
f.setSize(d);
if (width > 20)
{
Timer t = (Timer) e.getSource();
t.stop();
}
}
});
f.add(jsp);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
timer.start();
}
public static void main(String[] args) throws Exception
{
new FlickerTest().create();
}
}
答案 0 :(得分:2)
仅供注意:在调整大小时闪烁是Win 7与Aero的已知问题: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6898838 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6873928
答案 1 :(得分:1)
不要在Timer中使用Thread.sleep()。你是阻止EDT响应事件和做画。
答案 2 :(得分:1)
这对你有用吗?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class FlickerTest
{
int width = 1;
private void create()
{
final JFrame f = new JFrame("JSplitPane");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p1 = new JPanel();
p1.setPreferredSize(new Dimension(100, 300));
JPanel p2 = new JPanel();
p2.setPreferredSize(new Dimension(0,0));
p2.setBackground(Color.gray);
JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, p1, p2);
jsp.setSize(new Dimension(400, 800));
Timer timer = new Timer(1, new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
width++;
int frameWidth = f.getWidth() + width;
if (width>1502) {
frameWidth = f.getWidth() + width - 1500;
}
Dimension d = new Dimension(frameWidth, f.getHeight());
f.setSize(d);
if (width > 1520)
{
Timer t = (Timer) e.getSource();
t.stop();
}
}
});
f.add(jsp);
f.pack();
//f.setLocationRelativeTo(null);
f.setVisible(true);
timer.start();
}
public static void main(String[] args) throws Exception
{
new FlickerTest().create();
}
}
BTW - 我们很多人没有监视器1500(+以说明UI在屏幕中间开始的事实)像素宽。
答案 3 :(得分:1)
夫妻建议:
setBounds
代替setSize
。不确定这是否有所不同,但可以更好地控制坐标。sleep()
中调用Timer
,而是在计时器上设置初始延迟setPreferredSize(0, 0)
public static class FlickerTest {
int width = 1;
private void create() {
final JFrame f = new JFrame("JSplitPane");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p1 = new JPanel();
p1.setPreferredSize(new Dimension(100, 300));
JPanel p2 = new JPanel();
p2.setBackground(Color.gray);
JSplitPane jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, p1, p2);
jsp.setSize(new Dimension(400, 800));
Timer timer = new Timer(30, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
width++;
int frameWidth = f.getWidth() + width;
Dimension d = new Dimension(frameWidth, f.getHeight());
f.setBounds(f.getX(), f.getY(), frameWidth, f.getHeight());
//f.setSize(frameWidth, f.getHeight());
if (width > 20) {
Timer t = (Timer) e.getSource();
t.stop();
}
}
});
f.add(jsp);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
timer.setInitialDelay(1500);
timer.start();
}
}
答案 4 :(得分:1)
这个技巧提高了Win7 + Aero中的重绘率:设置可调整为null,并提供自己的调整大小钩子。它不是完美的,但仍然更好..检查我的例子:
import java.awt.event.*;
import java.awt.*;
import javax.swing.event.*;
import javax.swing.*;
class ResizeHookDemo extends JDialog {
private final static int width = 580, height = 350;
private final JFileChooser fc;
private java.awt.geom.GeneralPath gp;
public ResizeHookDemo() {
super((JDialog)null, "Choose File", true);
fc = new JFileChooser() {
@Override
public void paint(Graphics g) {
super.paint(g);
int w = getWidth();
int h = getHeight();
g.setColor(new Color(150, 150, 150, 200));
g.drawLine(w-7, h, w, h-7);
g.drawLine(w-11, h, w, h-11);
g.drawLine(w-15, h, w, h-15);
gp = new java.awt.geom.GeneralPath();
gp.moveTo(w-17, h);
gp.lineTo(w, h-17);
gp.lineTo(w, h);
gp.closePath();
}
};
fc.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("CancelSelection")) {
setVisible(false);
// action...
}
else if (e.getActionCommand().equals("ApproveSelection")) {
setVisible(false);
// action...
}
}
});
MouseInputListener resizeHook = new MouseInputAdapter() {
private Point startPos = null;
public void mousePressed(MouseEvent e) {
if (gp.contains(e.getPoint()))
startPos = new Point(getWidth()-e.getX(), getHeight()-e.getY());
}
public void mouseReleased(MouseEvent mouseEvent) {
startPos = null;
}
public void mouseMoved(MouseEvent e) {
if (gp.contains(e.getPoint()))
setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
else
setCursor(Cursor.getDefaultCursor());
}
public void mouseDragged(MouseEvent e) {
if (startPos != null) {
int dx = e.getX() + startPos.x;
int dy = e.getY() + startPos.y;
setSize(dx, dy);
repaint();
}
}
};
fc.addMouseMotionListener(resizeHook);
fc.addMouseListener(resizeHook);
fc.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 20));
add(fc);
setResizable(false);
setMinimumSize(new Dimension(width, height));
setDefaultCloseOperation(HIDE_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String args[]) {
System.out.println("Starting demo...");
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ResizeHookDemo().setVisible(true);
}
});
}
}
答案 5 :(得分:0)
对于我来说,将noerasebackround变为真正的工作:
System.setProperty("sun.awt.noerasebackground", "true");
答案 6 :(得分:-1)
对此感到抱歉 - 我毫不犹豫地删掉了我的答案。是的,不应在Swing中使用更新。
为了弥补这一点,我发现了一篇OS X Swing家伙的博客文章,他在第2段写道:“程序化调整大小目前会导致Mac上的Java闪烁。”
http://explodingpixels.wordpress.com/2008/09/28/the-heads-up-display-hud/
由于你的代码在我运行时不会引起闪烁(在这里工作的旧机器上),看来上面的情况仍然如此。