【问题标题】:How to paint a JPanel only by a JButton press?如何仅通过按下 JButton 来绘制 JPanel?
【发布时间】:2017-05-03 23:36:03
【问题描述】:

这是一个应用程序的片段,其中有几个标签挂在 JTabbedPanel 上:-

我已经按照以下标准方式使用代码生成了图像:-

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.drawImage(device.getVisualisation(), 0, 0, null);
}

因此,每当应用程序 gui 发生问题时,都会调用 paintComponent 方法并显示图像。这很正常。

如果选项卡焦点发生变化,或者鼠标如您预期的那样经过选项卡,也会发生此绘制事件。问题是这需要几秒钟,因为生成图形需要很多时间。这种延迟是不可避免的,我接受它。当 gui 系统完成它必须做的事情时,您还会获得许多绘制事件。通常这没问题,但由于处理延迟,gui 在 10 秒内停止 /flashes /updates 几次。

我认为我可以通过仅从 gui 上某处的“REFRESH”JButton 手动调用 repaint() 来解决此问题。但是,如果您使用选项卡,我将无法关闭自动重绘。如何通过按下按钮而不是自动绘制组件?

【问题讨论】:

    标签: java swing user-interface graphics


    【解决方案1】:

    我会做一些不同的事情,首先弄清楚这里的昂贵过程是什么。不是绘画,而是绘画所展现的特殊形象的计算和创造。因此,考虑到这一点,与其关闭仅涉及拼凑的绘画,不如将绘制的图像存储在一个图像字段中,并仔细控制何时通过昂贵的device.getVisualisation() 方法重新创建它。

    如果这个方法真的是长时间运行的,那么它就不会在paintComponent中调用它,这个方法永远不应该包含cpu-intense或time crunching代码,事实上,该方法应该从Swing事件中调用线程,而是在后台线程中。然后当后台线程完成处理后,更新相同的 BufferedImage 并调用repaint(),并显示新图像。

    例如:

    private Image image = null; // holds our image
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        if (image != null) {
            // this will hardly take any time at all to run
            g2d.drawImage(image, 0, 0, this);
        }
    }
    
    public void myDrawImage() {
    
        // create a SwingWorker for background threading work
        new SwingWorker<Image, Void>() {
    
            @Override
            protected Image doInBackground() throws Exception {
    
                // run this long-running code within this background thread
                return device.getVisualisation();
            };
    
            @Override
            protected void done() {
                try {
                    // when the thread is done, get the new image, 
                    // put it into our image field, and repaint the component
                    image = get();
                    repaint();
                } catch (InterruptedException | ExecutionException e) {
                    // TODO handle any exceptions that occur with drawing
                }
            };
        }.execute();
    }
    

    现在绘制的图像只会在您的程序专门调用myDrawImage() 方法时发生变化,因此现在长时间运行的代码的调用完全在您的控制之下。

    【讨论】:

    • 是的,这是一个长期运行的过程——它正在慢慢地从我无法控制(速度)控制的自定义硬件设备中提取数据,然后将其呈现。既然它摆在我面前,这显然是前进的方向……
    • 简单说明一下,myDrawImage /SwingWorker 代码在哪里?它会进入我的“REFRESH”jButton 吗?它不能是 jTabbedPanel 组件的一部分吗?
    • @PaulUszak:它去任何需要的地方。
    猜你喜欢
    • 2018-08-09
    • 1970-01-01
    • 2012-12-10
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多