У меня есть JTextPane в очень простом графическом интерфейсе, который я использую в качестве консоли вывода для игры, которую я использую для изучения Java, которую я (пытаюсь) использовать с методом добавления в классе окна, вызывая его из другого класса (программа сам) или из класса чтения команд. Теоретически он должен выводить набранную мной команду, а в следующих строках - вывод, полученный из указанной программы.
Метод печати (который использует append для JTextArea или getText () и setText () для JTextPane) работает нормально, если он вызывается из собственного класса (при печати используемой команды и символа ">", однако при вызове извне он ведет себя случайным образом, иногда добавляя в самый верх textArea, работая как задумано, или даже дублируя весь текст внутри него.
Это код графического интерфейса, который используется для этого. Я уверен, что это не идеально или даже близко, но я только начал изучать основы графического интерфейса
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.DefaultCaret;
import graficos.VisorJugador;
public class test extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private String comando = "";
private JTextArea txp_Console;
private JScrollPane jsp_ConsoleScrollPanel;
private JLabel lbl_habitacion;
private VisorJugador[] jugadores;
/**
* Create the frame.
*/
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 640, 480);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
createPanels();
}
public static void lanzar(test frame){
frame.setVisible(true);
}
private void createPanels(){
JPanel panelInferior = new JPanel();
JPanel panelCentral = new JPanel();
panelCentral.setLayout(new BorderLayout(0, 0));
crearInferior(panelInferior);
crearCentral(panelCentral);
contentPane.add(panelInferior, BorderLayout.SOUTH);
contentPane.add(panelCentral, BorderLayout.CENTER);
}
private void crearCentral(JPanel panelCentral) {
JLabel lbl_Consola = new JLabel("Consola");
txp_Console = new JTextArea();
jsp_ConsoleScrollPanel = new JScrollPane(txp_Console);
txp_Console.setEditable(true);
DefaultCaret caret = (DefaultCaret) txp_Console.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
panelCentral.add(lbl_Consola, BorderLayout.NORTH);
panelCentral.add(txp_Console, BorderLayout.CENTER);
}
private void crearInferior(JPanel panelInferior) {
JLabel lbl_QueHacer = new JLabel("Que quieres hacer?");
JButton btn_Enviar = new JButton("Hacer");
JTextField txt_consola = new JTextField();
btn_Enviar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
comando = txt_consola.getText();
print("> " + txt_consola.getText());
txt_consola.setText("");
}
});
txt_consola.setColumns(10);
panelInferior.add(lbl_QueHacer, BorderLayout.NORTH);
panelInferior.add(txt_consola);
panelInferior.add(btn_Enviar);
}
public void print(String texto) {
String anterior = txp_Console.getText();
txp_Console.setText(anterior + texto);
}
}
Я вызываю ventana.print (labels.getString (msg)) каждый раз, когда мне нужно вывести что-то из программы, вентана - это новый экземпляр контрольная работа, созданный в его конструкторе. У меня нет понимания потоковой передачи, поэтому я ничего не могу с этим поделать, поэтому, насколько мне известно, все работает в основном потоке.
Кроме того, вот несколько примеров вывода
No entiendo --From commands 2 and 3
No entiendo --From commands 2 and 3
Bienvenido al Mundo de Zuul! --Working output
El Mundo de Zuul es un juego de aventuras muy aburrido, pero interesante!. --Working output
Escribe 'ayuda' si necesitas ayuda. --Working output
Estas en el exterior de la entrada principal de la universidad --Working output
Salidas: este, sur, oeste --Working output
> 1 --Works as intended
No entiendo --Output for command 1
> 2 --Output at the top
> 3 --Output at the top
> 4 --No output, windows error sound
Во время отладки я увидел, что создается поток для swing / awt, но я совсем не понимаю потоки, поэтому я просто надеюсь, что они мне не нужны для этого. Я также пробовал настраивать перо, перемещать полосу прокрутки, удалять "/ n" из команд, но пока не повезло.
... и ваше редактирование не сообщает нам намного больше информации об использовании. Снова нам нужно увидеть задействованный код, снова прочитайте ссылку на урок, так как мы можем дать совет, но мы не можем научить вас такой большой теме, как многопоточность, и вы должны изучить ее, и нужно.
См. Правки для ответа на пример работающего кода.




Вероятно, вы не используете потоки, но мы не видим проблемного кода, поэтому трудно сказать. Я скажу одну вещь: вы всегда должны запускать свой графический интерфейс в потоке событий Swing и стремиться вносить изменения в свой графический интерфейс в этом же потоке.
Одно изменение, которое вы можете внести в метод печати, - это проверить, находитесь ли вы в потоке событий Swing, и если да, добавьте текст, переданный в JTextArea. Если нет, то создайте код, используя SwingUtilities, чтобы поставить это изменение в очередь в потоке событий, примерно так:
public void print(String texto) {
// String anterior = txp_Console.getText();
// txp_Console.setText(anterior + texto);
if (SwingUtilities.isEventDispatchThread()) {
// if on the Swing event thread, call directly
txp_Console.append(texto); // a simple append call is all that is needed
} else {
// else queue it onto the event thread
SwingUtilities.invokeLater(() -> txp_Console.append(texto));
}
}
Прочтите Урок: Параллелизм в Swing, чтобы узнать больше о потоковой передаче Swing.
Например, скажем, у меня был такой графический интерфейс:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class JuanjoTestPanel extends JPanel {
private static final int TA_ROWS = 25;
private static final int TA_COLS = 60;
private JTextArea textArea = new JTextArea(TA_ROWS, TA_COLS);
private JTextField textField = new JTextField(30);
private Action hacerAction = new HacerAction();
public JuanjoTestPanel() {
textArea.setFocusable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
textField.setAction(hacerAction);
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JLabel("¿Que queres hacer?"));
bottomPanel.add(Box.createHorizontalStrut(5));
bottomPanel.add(textField);
bottomPanel.add(new JButton(hacerAction));
setLayout(new BorderLayout());
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
public void printToWindow(final String text) {
if (SwingUtilities.isEventDispatchThread()) {
textArea.append("Console:" + text + "\n");
} else {
SwingUtilities.invokeLater(() -> textArea.append("Console:" + text + "\n"));
}
}
private class HacerAction extends AbstractAction {
public HacerAction() {
super("Hacer");
putValue(MNEMONIC_KEY, KeyEvent.VK_H);
}
@Override
public void actionPerformed(ActionEvent e) {
String text = "> " + textField.getText() + "\n";
textArea.append(text);
textField.selectAll();
textField.requestFocusInWindow();
}
}
}
Вы также можете писать в него с консоли, вызывая его метод printToWindow(...) следующим образом:
import java.util.Scanner;
import javax.swing.*;
public class TestSwing2 {
private static final String EXIT = "exit";
public static void main(String[] args) {
// create window
final JuanjoTestPanel testPanel = new JuanjoTestPanel();
// launch it on the Swing event thread
SwingUtilities.invokeLater(() -> createAndShowGui(testPanel));
Scanner scanner = new Scanner(System.in);
String line = "";
while (!line.trim().equalsIgnoreCase(EXIT)) {
System.out.print("Enter text: ");
line = scanner.nextLine();
System.out.println("Line entered: " + line);
testPanel.printToWindow(line); // write to it
}
scanner.close();
System.exit(0);
}
private static void createAndShowGui(JuanjoTestPanel testPanel) {
JFrame frame = new JFrame("Test Swing2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(testPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
1-й пример работает как шарм и кажется более простым и понятным способом его реализации. Также подробно рассмотрим отредактированные дополнения. Действительно, очень ценится.
Мы не видим код проблемы - как вы используете этот класс, как вы вызываете print (который должен просто вызывать
txp_Console.append(texto)) и как вы обрабатываете потоки. Пожалуйста, отправьте действительныйминимальный воспроизводимый пример (прочтите ссылку) с вашим вопросом, чтобы мы могли сами протестировать код вашей проблемы. А также прочтите Урок: Параллелизм в Swing, который, вероятно, объяснит и поможет вам решить ваши проблемы. Пришло время изучить и понять многопоточность.