重绘线程在触发业务功能时工作正常,但在引用触发时冻结

发布于 2024-10-24 18:19:05 字数 3204 浏览 1 评论 0原文

解释起来有点困难,但情况是这样的:

我正在编写一个单元自动化程序,并且有一个扩展 JFrame 的 mainScreen 类,并且 JFrame 包含自定义 Jpanel,它也是一个继续重新绘制自身的线程。主类(App)创建主屏幕。

现在奇怪的是,当我从 App 类调用业务函数(即在 while 循环中涉及单元格)时,它正在工作(各代的实时视图),但是当我从主屏幕调用相同的函数时,它正在工作(各代的实时视图)类(通过键盘输入)然后重新绘制不符合,但我看到几代人正在参与的控制台输出..并且程序没有响应窗口的关闭十字,并且在其他情况下它关闭就像运行算法时正常。

那么,为什么我的 Jpanel 没有重新绘制? 希望各位(女孩)能够帮忙。

类关系:App<-MainScreen<-MapPanel

App

package Business;

import GUI.MainScreen;
import java.util.Random;

public class App {
    public static final int _CELL_SIZE = 5;
    public static final int _WIN_WIDTH = 800;
    public static final int _WIN_HEIGTH = 600;
    public static final int _HELP_HEIGTH = 72;
    public static final double _LIFE_START = 0.1F;

    private MainScreen _mainScreen;
    private Cell[][] _map;
    private int _generation;
    private Random _random;
    private boolean _running;

public App() {
    _generation = 0;
    _running = false;
    _random = new Random(System.currentTimeMillis());
    newMap();
    _mainScreen = new MainScreen(this);
    //envolveCells();
    //cout();
}

public void envolveCells() {
    _generation = 0;
    _running = true;
    Cell[][] newMap = new Cell[getNumOfRows()][getNumOfCells()];

    while(_running) {
        newMap = new Cell[getNumOfRows()][getNumOfCells()];

        //envolve cells
        for(int row = 0; row < getNumOfRows(); row++) {
            for(int cell = 0; cell < getNumOfCells(); cell++) {
                System.out.println(_map[row][cell].envolve());
                newMap[row][cell] = new Cell(_map[row][cell].envolve());
                newMap[row][cell].setNeighbors(_map[row][cell].getNeighbors());
            }
        }

        _map = newMap;
        _generation++;

        try {
            Thread.sleep(100);
        } catch(Exception ex) { }
    }
}

包GUI;

导入 Business.App; 导入 java.awt.event.KeyEvent; 导入 java.awt.event.KeyListener; 导入 javax.swing.JFrame;

公共类 MainScreen 扩展 JFrame 实现 KeyListener { 私人应用程序_app; 私有地图面板_mapPanel;

public MainScreen(App app){
    _app = app;
    _mapPanel = new MapPanel(app);

    setTitle("Cellular Automaton sandbox - Sven van Zoelen");
    setSize(App._WIN_WIDTH, App._WIN_HEIGTH + App._HELP_HEIGTH);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    add(_mapPanel);
    addKeyListener(this);

    setVisible(true);
}

public void keyTyped(KeyEvent e) {
    if(e.getKeyChar() == 'r') {
        System.out.println("Run mode");
        _app.envolveCells();
    }
}

地图面板

package GUI;

import Business.App;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public class MapPanel extends JPanel implements Runnable {
    private App _app;
    private Font _font = new Font("Arial", Font.PLAIN, 10);

public MapPanel(App app) {
    _font = new Font("Arial", Font.PLAIN, 10);
    _app = app;

    new Thread(this).start();
}
....
public void run() {
    while(true) {
        repaint();

        try {
            Thread.sleep(50);
        } catch(Exception ex) { }
    }
  }
}

It's a bit difficult to explain but here is the situation:

I'm programming a Cellular Automation program and have a mainScreen class that extends the JFrame and that JFrame includes the custom Jpanel that is also a thread that continues to repaint his self. The main class (App) creates the mainScreen.

Now is the strange thing that it is working (real-time view of the generations) when i call the business function (that is envolving the cells in a while loop) from the App class, but when i call the same function from the MainScreen class (through keyboard input) then the repainting doesn't accour, but i see console output that the generations are envolving.. And the program isn't responding to the close cross of the window, and in the other scenario it closes just like normal when running the algorithm.

So, why isn't my Jpanel repainting?
Hope you guys (girls) can help.

Class relation: App<-MainScreen<-MapPanel

App

package Business;

import GUI.MainScreen;
import java.util.Random;

public class App {
    public static final int _CELL_SIZE = 5;
    public static final int _WIN_WIDTH = 800;
    public static final int _WIN_HEIGTH = 600;
    public static final int _HELP_HEIGTH = 72;
    public static final double _LIFE_START = 0.1F;

    private MainScreen _mainScreen;
    private Cell[][] _map;
    private int _generation;
    private Random _random;
    private boolean _running;

public App() {
    _generation = 0;
    _running = false;
    _random = new Random(System.currentTimeMillis());
    newMap();
    _mainScreen = new MainScreen(this);
    //envolveCells();
    //cout();
}

public void envolveCells() {
    _generation = 0;
    _running = true;
    Cell[][] newMap = new Cell[getNumOfRows()][getNumOfCells()];

    while(_running) {
        newMap = new Cell[getNumOfRows()][getNumOfCells()];

        //envolve cells
        for(int row = 0; row < getNumOfRows(); row++) {
            for(int cell = 0; cell < getNumOfCells(); cell++) {
                System.out.println(_map[row][cell].envolve());
                newMap[row][cell] = new Cell(_map[row][cell].envolve());
                newMap[row][cell].setNeighbors(_map[row][cell].getNeighbors());
            }
        }

        _map = newMap;
        _generation++;

        try {
            Thread.sleep(100);
        } catch(Exception ex) { }
    }
}

package GUI;

import Business.App;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;

public class MainScreen extends JFrame implements KeyListener {
private App _app;
private MapPanel _mapPanel;

public MainScreen(App app){
    _app = app;
    _mapPanel = new MapPanel(app);

    setTitle("Cellular Automaton sandbox - Sven van Zoelen");
    setSize(App._WIN_WIDTH, App._WIN_HEIGTH + App._HELP_HEIGTH);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    add(_mapPanel);
    addKeyListener(this);

    setVisible(true);
}

public void keyTyped(KeyEvent e) {
    if(e.getKeyChar() == 'r') {
        System.out.println("Run mode");
        _app.envolveCells();
    }
}

MapPanel

package GUI;

import Business.App;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public class MapPanel extends JPanel implements Runnable {
    private App _app;
    private Font _font = new Font("Arial", Font.PLAIN, 10);

public MapPanel(App app) {
    _font = new Font("Arial", Font.PLAIN, 10);
    _app = app;

    new Thread(this).start();
}
....
public void run() {
    while(true) {
        repaint();

        try {
            Thread.sleep(50);
        } catch(Exception ex) { }
    }
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉城凉梦凉人心 2024-10-31 18:19:05

您的“业务逻辑”看起来应该在与 GUI 不同的线程上运行。因此,不要直接从 GUI 线程(在操作侦听器中)调用它,而是将其放在一个新线程中。

只要你的动作监听器(或者本例中的键监听器)没有返回,你的 GUI 就不会被绘制,因为绘制与输入处理发生在同一个线程中。

public void keyTyped(KeyEvent e) {
    if(e.getKeyChar() == 'r') {
        new Thread("envolver") { public void run() {
           System.out.println("Run mode");
           _app.envolveCells();
        }).start();
    }
}

Your "business logic" looks like it should run at a separate thread from the GUI. Thus, don't invoke it directly from the GUI thread (in the action listener), but put it in a new Thread there.

As long as your action listener (or key-listener, in this case) does not return, your GUI will not be painted, as painting occurs in the same thread as input-handling.

public void keyTyped(KeyEvent e) {
    if(e.getKeyChar() == 'r') {
        new Thread("envolver") { public void run() {
           System.out.println("Run mode");
           _app.envolveCells();
        }).start();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文