为什么这不一致?

时间:2013-08-30 17:32:23

标签: java swing jframe awt joptionpane

我写了一个快速测试程序,它接受一个字符串输入并在JFrame上绘制它。超级简单。但出于某种原因,该计划并不是一致的。如同输入一样,它并不总是将字符串绘制到屏幕上。为了尝试和调试,我添加了一个repaint(); to paintComponent(反复要求绘制输入,因此我添加了双缓冲区)。当程序决定不绘制到框架时,它没有使它重绘();并且没有显示新的输入对话框。我无法理解为什么。

package test;
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Main extends JFrame {

private Image dbImage;
private Graphics dbg;

public Main() {
    setTitle("Test Project");
    setSize(300, 300);
    setVisible(true);
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public void paint(Graphics g) {
    dbImage = createImage(getWidth(), getHeight());
    dbg = dbImage.getGraphics();
    paintComponent(dbg);
    g.drawImage(dbImage, 0, 0, this);
}

public void paintComponent(Graphics g) {
    g.drawString(input(), 140, 130);
}

public static String input() {
    String x = ((String)JOptionPane.showInputDialog (
        null, "Enter a string", "Test Project",
        JOptionPane.QUESTION_MESSAGE,
        null, null, null));
    return x;
}

public static void main(String[] args) {
    Main main = new Main();

}
}

一个注意事项:最初,输入法是在一个单独的类中,因为这就是我正在测试它的项目。为了简洁起见,我把它移到这里,因为无论方法在哪里,问题仍然会出现。

2 个答案:

答案 0 :(得分:2)

从我的评论中得出理论:-)

为我的评论添加更多积分:

  • 而不是在setSize()上使用JFrame,而是覆盖getPreferredSize()方法,而不是您扩展的任何JComponent/JPanel。现在只需在pack()上调用JFrame,就可以计算出自己的大小。
  • 请阅读Concurrency in Swing

以下是我所说的实例:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main extends JPanel {

    private JButton button; 
    private String message;

    private ActionListener buttonAction = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            message = input();
            repaint();
        }
    };

    public Main() {
        message = "Nothing to display yet...";
    }

    private void displayGUI() {
        JFrame frame = new JFrame("Painting Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel(new BorderLayout(5, 5));
        button = new JButton("Get Message");
        button.addActionListener(buttonAction);

        contentPane.add(this, BorderLayout.CENTER);
        contentPane.add(button, BorderLayout.PAGE_END);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    @Override
    public Dimension getPreferredSize() {
        return (new Dimension(200, 200));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString(message, 50, 50);
    }

    public String input() {
        String x = ((String)JOptionPane.showInputDialog (
                null, "Enter a string", "Test Project",
                            JOptionPane.QUESTION_MESSAGE,
                                        null, null, null));
        return x;
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new Main().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

编辑1:

如果您不想使用JButton来提问,可以在MouseListener上添加JPanel,如下图所示:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main extends JPanel {

    private String message;
    private int x;
    private int y;

    private MouseAdapter mouseAction = new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent me) {
            message = input();
            x = me.getX();
            y = me.getY();
            repaint();
        }
    };

    public Main() {
        message = "Nothing to display yet...";
        x = y = 0;
    }

    private void displayGUI() {
        JFrame frame = new JFrame("Painting Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel(new BorderLayout(5, 5));

        addMouseListener(mouseAction);
        contentPane.add(this, BorderLayout.CENTER);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    @Override
    public Dimension getPreferredSize() {
        return (new Dimension(200, 200));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString(message, x, y);
    }

    public String input() {
        String x = ((String)JOptionPane.showInputDialog (
                null, "Enter a string", "Test Project",
                            JOptionPane.QUESTION_MESSAGE,
                                        null, null, null));
        return x;
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new Main().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

答案 1 :(得分:2)

你的代码有很多问题,我写了一个新程序来做同样的事情。我确实保留了你的输入法。

我建议你花一点时间研究Oracle Swing Tutorial

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SimpleInput implements Runnable {

    @Override
    public void run() {
        JFrame frame = new JFrame("String Display");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);

        DrawingPanel drawingPanel = new DrawingPanel();
        frame.add(drawingPanel);

        frame.pack();
        frame.setVisible(true);

        new Thread(new DisplayRunnable(drawingPanel)).start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new SimpleInput());
    }

    public class DrawingPanel extends JPanel {
        private static final long   serialVersionUID    = 7580353846463376668L;

        private String text;

        public DrawingPanel() {
            this.setPreferredSize(new Dimension(300, 200));
            this.text = " ";
        }

        public void setText(String text) {
            this.text = text;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            FontRenderContext frc = g2d.getFontRenderContext();
            TextLayout layout = new TextLayout(text, g.getFont(), frc);
            Rectangle2D bounds = layout.getBounds();

            int width = (int) Math.round(bounds.getWidth());
            int height = (int) Math.round(bounds.getHeight());
            int x = (getWidth() - width) / 2;
            int y = height + (getHeight() - height) / 2;

            layout.draw(g2d, (float) x, (float) y);
        }

    }

    public class DisplayRunnable implements Runnable {

        private String displayString = " ";

        private DrawingPanel drawingPanel;

        public DisplayRunnable(DrawingPanel drawingPanel) {
            this.drawingPanel = drawingPanel;
        }

        @Override
        public void run() {
            long sleep = 5L;

            while ((displayString != null) && (!displayString.equals(""))) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        drawingPanel.setText(displayString);
                        drawingPanel.repaint();
                    }   
                });


                try {
                    Thread.sleep(sleep);
                } catch (InterruptedException e) {
                }


                displayString = input();
                sleep = 3000L;
            }

        }

        public String input() {
            String x = ((String) JOptionPane.showInputDialog(drawingPanel,
                    "Enter a string", "Test Project", JOptionPane.QUESTION_MESSAGE,
                    null, null, null));
            return x;
        }

    }
}