1

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

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();

}
}

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

4

2 回答 2

2

从我的评论中获取理论:-)

在我的评论中添加更多要点:

  • 对于您扩展的任何内容,而不是setSize()JFrame, 而不是覆盖getPreferredSize()方法上使用。JComponent/JPanel现在只需调用pack(),JFrame来计算它自己的大小。
  • 请阅读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:

如果你不喜欢使用JButtonfor 询问输入,你可以在你绘图的地方添加一个MouseListenerJPanel如下例所示:

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);
    }
}
于 2013-08-30T18:13:01.933 回答
2

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

我建议您花点时间学习Oracle Swing 教程

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;
        }

    }
}
于 2013-08-30T18:13:54.120 回答