gpt4 book ai didi

Java 线程不能与 JTextArea 一起正常工作

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:02:39 25 4
gpt4 key购买 nike

在 Java 中,我目前正在创建一个登录/注册程序(希望将来扩展它)但是遇到了问题。

我试图让文本以动画类型的作家风格出现在屏幕上。

当我运行该类的 main 方法时,文本显示得很好,当我在 keylistener 中运行它时,它失败并等待文本出现,然后更新框架以便我可以看到它。

源代码如下:

登录类

public class Login implements KeyListener {

int BACK_WIDTH = java.awt.Toolkit.getDefaultToolkit().getScreenSize().width;
int BACK_HEIGHT = java.awt.Toolkit.getDefaultToolkit().getScreenSize().height;

JFrame back_frame = new JFrame();

LoginTerminal login = new LoginTerminal();

public Login() {
back_frame.setSize(BACK_WIDTH, BACK_HEIGHT);
back_frame.setLocation(0, 0);
back_frame.getContentPane().setBackground(Color.BLACK);
back_frame.setUndecorated(true);
//back_frame.setVisible(true);

back_frame.addKeyListener(this);
login.addKeyListener(this);
login.setLocationRelativeTo(null);
login.setVisible(true);
login.field.addKeyListener(this);

login.slowPrint("Please login to continue...\n"
+ "Type 'help' for more information.\n");
}

public void keyPressed(KeyEvent e) {
int i = e.getKeyCode();

if(i == KeyEvent.VK_ESCAPE) {
System.exit(0);
}

if(i == KeyEvent.VK_ENTER) {
login.slowPrint("\nCommands\n"
+ "-----------\n"
+ "register\n"
+ "login\n");
}
}

public void keyReleased(KeyEvent e) {}

public void keyTyped(KeyEvent e) {}

}

LoginTerminal.class

public class LoginTerminal implements KeyListener {

CustomFrame frame = new CustomFrame(Types.TERMINAL);

JTextArea log = new JTextArea();
public JTextField field = new JTextField();

public void setVisible(boolean bool) {
frame.setVisible(bool);
}

public void addKeyListener(KeyListener listener) {
frame.addKeyListener(listener);
}

public void slowPrint(String str) {
for(int i = 0; i < str.length(); i++) {
log.append("" + str.charAt(i));

try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}

if (i == str.length() - 1) {
log.append("\n");
}
}
}

public void setLocation(int x, int y) {
frame.setLocation(x, y);
}

public void setLocationRelativeTo(Component c) {
frame.setLocationRelativeTo(c);
}

public LoginTerminal() {
try {

InputStream is = LoginTerminal.class.getResourceAsStream("/fonts/dungeon.TTF");
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
font = font.deriveFont(Font.PLAIN, 10);

frame.add(field);
frame.add(log);

log.setBackground(Color.BLACK);
log.setForeground(Color.WHITE);
log.setWrapStyleWord(true);
log.setLineWrap(true);
log.setBounds(4, 20 + 4, frame.getWidth() - 8, frame.getHeight() - 50);
log.setFont(font);
log.setEditable(false);
log.setCaretColor(Color.BLACK);

field.setBackground(Color.BLACK);
field.setForeground(Color.WHITE);
field.setBounds(2, frame.getHeight() - 23, frame.getWidth() - 5, 20);
field.setFont(font);
field.setCaretColor(Color.BLACK);
field.addKeyListener(this);
field.setText(" > ");

} catch (FontFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public void dumpToLog() {
log.append(field.getText() + "\n");
field.setText(" > ");
}

public void keyPressed(KeyEvent e) {
int i = e.getKeyCode();

if(i == KeyEvent.VK_ENTER && field.isFocusOwner()) {
if(field.getText().equals(" > HELP") || field.getText().equals(" > help")) {
dumpToLog();


} else {
dumpToLog();
}
}


if(!field.getText().startsWith(" > ")) {
field.setText(" > ");
}
}

public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}

}

主类

public class Main {

public static void main(String[] args) {
new Login();
}

}

我的问题是:

public Login() {
login.slowPrint("Please login to continue...\n"
+ "Type 'help' for more information.\n");
}

当我运行它时,它按预期工作。

下面是同一个类(Login.class)

public void keyPressed(KeyEvent e) {
int i = e.getKeyCode();

if(i == KeyEvent.VK_ENTER) {
login.slowPrint("\nCommands\n"
+ "-----------\n"
+ "register\n"
+ "login\n");
}
}

它卡住并等待完成。

我认为可能是 Thread.sleep(50);在 LoginTerminal.class 中,如标题所述,因为这是触发打字动画的事实。

希望我在这里说清楚了。感谢大家的帮助!

编辑

这就是导致计时器错误的原因...

public void timerPrint(String text) {
Timer timer = new Timer(50, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (index < text.length() - 1 && index >= 0) {
String newChar = Character.toString(text.charAt(index));
textArea.append(newChar);
index++;
} else {
textArea.setText(null);
index = 0;
// You could stop the timer here...
}
}
});
timer.start();
}

构造函数 Timer(int, new ActionListener(){}) 未定义

编辑编辑,全类:

package com.finn.frametypes;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.Timer;

import com.finn.gui.CustomFrame;
import com.finn.gui.Types;

public class LoginTerminal implements KeyListener {

CustomFrame frame = new CustomFrame(Types.TERMINAL);

JTextArea log = new JTextArea();
public JTextField field = new JTextField();

public void setVisible(boolean bool) {
frame.setVisible(bool);
}

public void addKeyListener(KeyListener listener) {
frame.addKeyListener(listener);
}
public void timerPrint(String text) {
Timer timer = new Timer(50, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (index < text.length() - 1 && index >= 0) {
String newChar = Character.toString(text.charAt(index));
textArea.append(newChar);
index++;
} else {
textArea.setText(null);
index = 0;
// You could stop the timer here...
}
}
});
timer.start();
}

public void slowPrint(String str) {
for(int i = 0; i < str.length(); i++) {
log.append("" + str.charAt(i));

try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}

if (i == str.length() - 1) {
log.append("\n");
}
}
}

public void setLocation(int x, int y) {
frame.setLocation(x, y);
}

public void setLocationRelativeTo(Component c) {
frame.setLocationRelativeTo(c);
}

public LoginTerminal() {
try {

InputStream is = LoginTerminal.class.getResourceAsStream("/fonts/dungeon.TTF");
Font font = Font.createFont(Font.TRUETYPE_FONT, is);
font = font.deriveFont(Font.PLAIN, 10);

frame.add(field);
frame.add(log);

log.setBackground(Color.BLACK);
log.setForeground(Color.WHITE);
log.setWrapStyleWord(true);
log.setLineWrap(true);
log.setBounds(4, 20 + 4, frame.getWidth() - 8, frame.getHeight() - 50);
log.setFont(font);
log.setEditable(false);
log.setCaretColor(Color.BLACK);

field.setBackground(Color.BLACK);
field.setForeground(Color.WHITE);
field.setBounds(2, frame.getHeight() - 23, frame.getWidth() - 5, 20);
field.setFont(font);
field.setCaretColor(Color.BLACK);
field.addKeyListener(this);
field.setText(" > ");

} catch (FontFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public void dumpToLog() {
log.append(field.getText() + "\n");
field.setText(" > ");
}

public void keyPressed(KeyEvent e) {
int i = e.getKeyCode();

if(i == KeyEvent.VK_ENTER && field.isFocusOwner()) {
if(field.getText().equals(" > HELP") || field.getText().equals(" > help")) {
dumpToLog();


} else {
dumpToLog();
}
}


if(!field.getText().startsWith(" > ")) {
field.setText(" > ");
}
}

public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}

}

回答

如果以后有人读到这篇文章并想在 Java 中使用慢打印,请使用以下内容:

int index;

public void timerPrint(final String text) {
Timer timer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (index < text.length() - 1 && index >= 0) {
String newChar = Character.toString(text.charAt(index));
textarea.append(newChar);
index++;
} else {
index = 0;
((Timer)e.getSource()).stop();
}
}
});
timer.start();
}

最佳答案

Swing 是一个单线程框架,也就是说,任何阻塞事件调度线程的东西都会阻止 UI 更新或让您的程序响应新线程

参见 Concurrency in Swing了解更多详情。

您永远不应在 EDT 中执行任何阻塞 (Thread.sleep) 或长时间运行的进程。

Swing 也不是线程安全的,这意味着您永远不应该从 EDT 上下文之外更新 UI。

这让你陷入了一个难题......

幸运的是,有很多选择。对于您的情况,最简单的解决方案可能是使用 Swing Timer,它可用于安排定期回调到 EDT,您可以在其中执行更新

参见 How to use Swing Timers了解更多详情

例如……

Scrolling Text

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ScrollingText100 {

public static void main(String[] args) {
new ScrollingText100();
}

public ScrollingText100() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private String text;
private int index;
private JTextArea textArea;

public TestPane() {
setLayout(new BorderLayout());
textArea = new JTextArea(2, 40);
add(textArea);

text = "Please login to continue...\n" + "Type 'help' for more information.\n";
Timer timer = new Timer(50, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (index < text.length() - 1 && index >= 0) {
String newChar = Character.toString(text.charAt(index));
textArea.append(newChar);
index++;
} else {
textArea.setText(null);
index = 0;
// You could stop the timer here...
}
}
});
timer.start();
}

}

}

已更新

如果我正确理解您的要求,像这样...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JScrollPane;

import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class LoginTerminal {

private JTextArea log = new JTextArea(20, 40);
private JTextField field = new JTextField();

private int index;
private StringBuilder textToDisplay;
private Timer timer;

public static void main(String[] args) {
new LoginTerminal();
}

public LoginTerminal() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

textToDisplay = new StringBuilder(128);
timer = new Timer(50, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (textToDisplay.length() > 0) {
String newChar = Character.toString(textToDisplay.charAt(0));
textToDisplay.delete(0, 1);
log.append(newChar);
} else {
((Timer) e.getSource()).stop();
}
}
});

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.add(field, BorderLayout.NORTH);
frame.add(new JScrollPane(log));

log.setBackground(Color.BLACK);
log.setForeground(Color.WHITE);
log.setWrapStyleWord(true);
log.setLineWrap(true);
log.setEditable(false);
log.setCaretColor(Color.BLACK);

field.setBackground(Color.BLACK);
field.setForeground(Color.WHITE);
field.setCaretColor(Color.BLACK);
field.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (" > HELP".equalsIgnoreCase(field.getText())) {
dumpToLog();
} else {
dumpToLog();
}
}
});
field.setText(" > ");

frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public void timerPrint(String text) {

textToDisplay.append(text).append("\n");
if (!timer.isRunning()) {
timer.start();
}
}

public void slowPrint(String str) {
for (int i = 0; i < str.length(); i++) {
log.append("" + str.charAt(i));

try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}

if (i == str.length() - 1) {
log.append("\n");
}
}
}

public void dumpToLog() {
timerPrint(field.getText());
}

}

可能是您真正要找的东西。

注意,KeyListener 不是 JTextComponent 的好选择,在这种情况下,ActionListener 是更好的选择。

关于Java 线程不能与 JTextArea 一起正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26754146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com