java - 在单独线程上刷新 Gui

标签 java multithreading swing repaint paintcomponent

我正在编写一个应用程序,我想在 map 上绘制一些标记和图片。但是这里我遇到了问题。当我按下按钮时,我以 30 毫秒的延迟启动线程。但实际上,该任务看起来像是在主线程上运行,导致 gui 停止刷新并且无法对其执行任何操作。 这是我的代码

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;

import javax.swing.JInternalFrame;
import javax.swing.JPanel;

public class MapDrawer extends JPanel
{
     Graphics testGrafika;
     DrawerThread drawingThread;

    public MapDrawer(JPanel drawPanel)
    {
        drawPanel.add(this);
        testGrafika=drawPanel.getGraphics();    
        paintComponent(testGrafika);
        drawingThread=new DrawerThread();
        drawingThread.run();            
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponents(g);
        this.setBackground(Color.WHITE);
        g.setColor(Color.BLUE);
        g.fillRect(10, 25, 200, 200);
    }

    public Graphics getGraphics()
    {
        return testGrafika;         
    }

    public class DrawerThread extends Thread implements Runnable
    {   
        @Override
        public void run()
        {
            while(true)
            {
                repaint();
                try {
                    DrawerThread.sleep(30);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

这是我的 GUI 类:

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JButton;
import java.awt.CardLayout;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;

import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.FlowLayout;
import javax.swing.border.EtchedBorder;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import org.eclipse.wb.swing.FocusTraversalOnArray;

import soft.MapDrawer;
import soft.MapView;

import java.awt.Component;
import javax.swing.JToggleButton;
import javax.swing.JRadioButton;
import javax.swing.JInternalFrame;
import java.awt.Canvas;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Dimension;
import javax.swing.JLayeredPane;

public class MainWindow {

    private JFrame frame;
    private JMenu MenuBasicActions;
    private JInternalFrame mapFrameRef;
    private JPanel drawPanelRef;

    /**
     * Launch the application.
     */
    public static void main(String[] args)
    {   
        EventQueue.invokeLater(new Runnable()

        {
            public void run() 
            {
                try 
                {
                    MainWindow window = new MainWindow();
                    window.frame.setVisible(true);
                } catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });

    }

    /**
     * Create the application.
     */
    public MainWindow()
    {
        initialize();               
    }

    public JFrame getMainFrame()
    {
        return frame;
    }

    public JPanel getDrawPanel()
    {
        return drawPanelRef;    
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setVisible(true);
        frame.setBounds(100, 100, 1024, 768);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);           

        JMenuBar menuBarUpper = new JMenuBar();
        frame.setJMenuBar(menuBarUpper);

        MenuBasicActions = new JMenu("GPS Settings");
        menuBarUpper.add(MenuBasicActions);

        JMenuItem mntmNewMenuItem = new JMenuItem("New menu item");
        MenuBasicActions.add(mntmNewMenuItem);

        JMenuItem mntmNewMenuItem_1 = new JMenuItem("New menu item");
        MenuBasicActions.add(mntmNewMenuItem_1);

        JMenuItem mntmNewMenuItem_2 = new JMenuItem("New menu item");
        MenuBasicActions.add(mntmNewMenuItem_2);

        JMenu DevicesMenu = new JMenu("Devices");
        menuBarUpper.add(DevicesMenu);

        JMenuItem mntmNewMenuItem_3 = new JMenuItem("New menu item");
        DevicesMenu.add(mntmNewMenuItem_3);

        JMenuItem mntmNewMenuItem_4 = new JMenuItem("New menu item");
        DevicesMenu.add(mntmNewMenuItem_4);

        JMenu HelpMenu = new JMenu("Help");
        menuBarUpper.add(HelpMenu); 

        JToolBar toolBar = new JToolBar();
        toolBar.setOrientation(SwingConstants.VERTICAL);
        frame.getContentPane().add(toolBar, BorderLayout.WEST);

        JButton btnNewButton_1 = new JButton("New button");
        btnNewButton_1.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent arg0)
            {
                paint();
            }
        });
        toolBar.add(btnNewButton_1);


        JButton btnNewButton = new JButton("New button");
        toolBar.add(btnNewButton);

        JButton btnNewButton_2 = new JButton("New button");
        toolBar.add(btnNewButton_2);

        JButton btnNewButton_3 = new JButton("New button");
        toolBar.add(btnNewButton_3);
        toolBar.setFocusTraversalPolicy(new FocusTraversalOnArray(new Component[]{btnNewButton_1, btnNewButton}));

        JInternalFrame mapFrame = new JInternalFrame("Military Tracking System");
        mapFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.getContentPane().add(mapFrame, BorderLayout.CENTER);
        mapFrame.setVisible(true);

        JPanel drawPanel = new JPanel();
        drawPanel.setOpaque(false);
        mapFrame.setGlassPane(drawPanel);
        drawPanel.setVisible(true);

        drawPanel.setBorder(null);
        //mapFrame.getContentPane().add(drawPanel, BorderLayout.CENTER);

        frame.setFocusTraversalPolicy(new FocusTraversalOnArray(new Component[]{frame.getContentPane(), toolBar, btnNewButton_1, btnNewButton, btnNewButton_2, btnNewButton_3, menuBarUpper, MenuBasicActions, mntmNewMenuItem, mntmNewMenuItem_1, mntmNewMenuItem_2, DevicesMenu, mntmNewMenuItem_3, mntmNewMenuItem_4, HelpMenu}));

        MapView hlavnaMapa=new MapView();
        hlavnaMapa.Init(mapFrame);  
        mapFrameRef=mapFrame;
        drawPanelRef=drawPanel;
    }

    public void paint()
    {
        MapDrawer drawer=new MapDrawer(drawPanelRef);
        //drawer.paintComponent(drawer.getGraphics());          
    }
}

我想要做的是在一个线程上运行 gui 并在另一个线程上绘制对象,这样我就可以控制 gui。

最佳答案

为了启动Thread,您应该调用drawingThread.start();而不是run()

start()然后将启动一个新线程并调用该线程内的方法run()。如果您改为调用 run() ,它将在与调用者相同的线程上运行。

关于java - 在单独线程上刷新 Gui,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14729314/

相关文章:

java - HashMap 到 JTable

java - 将应用程序转换为 MVC 架构

java - 必须在tomcat中进行配置才能进行产品配置吗?

java - 从错误的线程异常调用

java - 更改 JLabel 字体大小

java - 在默认 JFrame 面板上使用 paintComponent()

java - 罗马数字转换器与其他转换器不同

Eclipse 无法启动

c++ - std::vectors 是线程安全的吗?

java - 为什么Java的HashTable是同步的?