为什么 JPanel 上没有任何显示?
Why is nothing is displayed on JPanel?
我正在尝试从数据库中获取数据并将结果发布到 JPanel
。
这是简化的代码:
public class LedgerView extends JPanel {
public LedgerView() {
super();
this.setLayout(new FlowLayout());
this.add(new JLabel("ITEMS:"));
String JDBC_DRIVER = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://localhost/gnufinance";
String USERNAME = "gnufinance";
String PASSWORD = "gnuisnotunix";
Connection conn = null;
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
String query = "SELECT * FROM transactions";
try {
PreparedStatement ps = conn.prepareStatement(query);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String desc = rs.getString(3);
System.out.println(desc);
this.add(new JLabel(desc));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame view = new JFrame();
view.setVisible(true);
view.setSize(300, 300);
view.add(new LedgerView(), BorderLayout.CENTER);
}
除了空白的灰色框外,没有显示任何内容,但是当我删除 JDBC 代码时,会显示第一个 JLabel(ITEMS)
。屏幕上没有任何内容,但 while 循环中的 System.out.println
会在控制台上正确打印所有数据。无一例外。
您必须在 Event Dispatch Thread 或美国东部时间创建面板。
Swing 不是线程安全的;您对 swing 控件所做的任何更改(例如创建新的 JLabel
s),必须在 EDT( 而不是 您的 main
方法启动的线程上发生上。您使用 EventQueue.invokeLater()
告诉 Java 将工作移到 Swing 绘图线程上。
请注意,大多数时候您不希望您的工作(如访问数据库)发生在 EDT 上,因为这会使您的用户界面无响应。换句话说,您的程序将执行访问数据库的工作,而不是绘制屏幕。
此代码将解决您眼前的问题,但您应该考虑在其他地方访问数据库(也许 暂时,在您的 main
方法中),存储生成 List
,然后将 List
传递给您的 LedgerView
,这将导致响应速度更快的用户界面。
public static void main(String[] args) {
final JFrame view = new JFrame();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
view.setSize(300, 300);
view.add(new LedgerView(), BorderLayout.CENTER);
view.setVisible(true);
}
}
}
我正在尝试从数据库中获取数据并将结果发布到 JPanel
。
这是简化的代码:
public class LedgerView extends JPanel {
public LedgerView() {
super();
this.setLayout(new FlowLayout());
this.add(new JLabel("ITEMS:"));
String JDBC_DRIVER = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://localhost/gnufinance";
String USERNAME = "gnufinance";
String PASSWORD = "gnuisnotunix";
Connection conn = null;
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
String query = "SELECT * FROM transactions";
try {
PreparedStatement ps = conn.prepareStatement(query);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String desc = rs.getString(3);
System.out.println(desc);
this.add(new JLabel(desc));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
JFrame view = new JFrame();
view.setVisible(true);
view.setSize(300, 300);
view.add(new LedgerView(), BorderLayout.CENTER);
}
除了空白的灰色框外,没有显示任何内容,但是当我删除 JDBC 代码时,会显示第一个 JLabel(ITEMS)
。屏幕上没有任何内容,但 while 循环中的 System.out.println
会在控制台上正确打印所有数据。无一例外。
您必须在 Event Dispatch Thread 或美国东部时间创建面板。
Swing 不是线程安全的;您对 swing 控件所做的任何更改(例如创建新的 JLabel
s),必须在 EDT( 而不是 您的 main
方法启动的线程上发生上。您使用 EventQueue.invokeLater()
告诉 Java 将工作移到 Swing 绘图线程上。
请注意,大多数时候您不希望您的工作(如访问数据库)发生在 EDT 上,因为这会使您的用户界面无响应。换句话说,您的程序将执行访问数据库的工作,而不是绘制屏幕。
此代码将解决您眼前的问题,但您应该考虑在其他地方访问数据库(也许 暂时,在您的 main
方法中),存储生成 List
,然后将 List
传递给您的 LedgerView
,这将导致响应速度更快的用户界面。
public static void main(String[] args) {
final JFrame view = new JFrame();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
view.setSize(300, 300);
view.add(new LedgerView(), BorderLayout.CENTER);
view.setVisible(true);
}
}
}