重绘时文本字段变形

Posted

技术标签:

【中文标题】重绘时文本字段变形【英文标题】:Text Field Deforming on Repaint 【发布时间】:2016-04-29 18:13:24 【问题描述】:

我有一个非常简单的 JFrame(它只包含一个文本字段和很多我绘制的内容),尽管每当调用 repaint() 时,文本字段都会发生变化。我很确定它是 repaint(),因为即使我将帧从一个监视器拖到下一个监视器以及在代码中调用它时也会发生这种情况。

当我运行程序时它开始正常:

但是,每当调用 repaint() 时,都会发生这种情况:

如果我开始在该字段中输入,其余部分会立即弹出并正常工作。最终,我的最终目标是将我的大部分框架重置为在 paintComponent() 中绘制的内容,同时仍然使文本字段可见。

我对图形和绘画比较陌生,非常感谢任何帮助!

编辑

在创建 SSCCE 时,我发现文本字段的问题是由我的 paintComponent 方法中的 Graphics2D 方法 rotate 引起的。我不知道为什么会这样,但我可以解决它并认为问题已解决。

现在,我遇到了一个新问题:我的 paintComponent 方法被调用了太多次。下面是这个问题的SSCCE,我希望事情发生的顺序是:

    调用paintComponent() (按下按钮时)调用 repaint() (按下按钮时,但在重绘之后)调用paintStuff()

这一切都发生了,但是后来以某种方式调用了paintComponent,擦除了由paintStuff()绘制的所有内容。

import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class tester extends JFrame 

    private JPanel contentPane;
    private JButton button;

    /**
     * Launch the application.
     */
    public static void main(String[] args) 
        EventQueue.invokeLater(new Runnable() 
            public void run() 
                try 
                    tester frame = new tester();
                    frame.setVisible(true);
                 catch (Exception e) 
                    e.printStackTrace();
                
            
        );
    

    /**
     * Create the frame.
     */
    public tester() 
        setBounds(100, 100, 450, 300);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        contentPane = new JPanel()
            public void paintComponent(Graphics g1) 
                System.out.println("draw rectangle - should be first");
                super.paintComponent(g1);

                g1.drawRect(50,50,50,50);
            
        ;
        contentPane.setLayout(null);
        setContentPane(contentPane);

        button = new JButton("Click me!");
        button.addActionListener(new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                System.out.println("repaint - should be second");
                repaint();

                paintStuff(contentPane.getGraphics());
            
        );
        button.setBounds(10, 11, 95, 20);
        contentPane.add(button);
    

    public void paintStuff(Graphics g)
        System.out.println("draw circle - should be last");
        g.drawOval(100,100,10,10);
    


【问题讨论】:

确保在您的paintComponent() 方法开始时调用super.paintComponent(...)。如果这没有帮助,请发布一个正确的SSCCE 来证明问题。 1) “我有一个非常简单的 JFrame(它只包含一个文本字段..” 哪里?那个代码显示了JButton,但没有JTextField . 2) 为文本字段设置大小的最佳方法是设置它需要显示的列数(字符)。调整其大小的另一种方法是更改​​它正在使用的Font 的大小。但更一般地说.. 3) .. .. 3) Java GUI 必须在不同的语言环境中使用不同的 PLAF 在不同的操作系统、屏幕尺寸、屏幕分辨率等上工作。因此,它们不利于像素完美布局。而是使用布局管理器,或 combinations of them 以及 white space 的布局填充和边框。 感谢您的提示,我会记住的。我将其更改为 SSCCE 中的一个按钮,以使我的第二个问题更易于理解。 【参考方案1】:
paintStuff(contentPane.getGraphics());

不,不要使用 getGraphics() 方法进行绘画。要重新绘制组件,您只需使用:

contentPane.repaint();

然后将 drawOval(...) 语句移至 paintComponent() 方法。

如果您想有条件地绘制椭圆,那么您需要为您的自定义绘画创建一个布尔属性。然后代码看起来像:

super.paintComponent(g1);

g1.drawRect(50,50,50,50);

if (drawOval)
    g1.drawOval(100,100,10,10);    

然后在您的课程中,您将创建一个类似的方法:

public void setDrawOval(Boolean drawOval)

    this.drawOval = drawOval;
    repaint();

所以在 ActionListener 中你只需使用:

contentPane.setDrawOval(true);

【讨论】:

以上是关于重绘时文本字段变形的主要内容,如果未能解决你的问题,请参考以下文章

在 MFC 中重绘时闪烁

SwiftUI:ObservableObject 在重绘时不会保持其状态

Today Extension 视图在重绘时闪烁

自定义视图在缩放后重绘时如何防止“反弹”效果?

.Net CF 防止过度、不耐烦的点击(屏幕重绘时)

尝试重绘时“数组索引超出范围:1”