2014-02-03 1 views
0

Я пытаюсь создать графический интерфейс Java динамически, беря значения из набора результатов и используя его для создания контрольного списка. Я создал небольшую демонстрационную программу, чтобы показать, что я сделал:Создание динамического GUI из ResultSet - Java

SQL команд

CREATE USER 'test'@'localhost' IDENTIFIED BY 'testpw'; 
CREATE DATABASE combotest; 
USE combotest; 

CREATE TABLE combotable (
id INT(5) NOT NULL PRIMARY KEY auto_increment, 
type VARCHAR(50) NOT NULL); 

INSERT INTO combotable (id, type) VALUES 
(default, 'Label'), 
(default, 'Textfield'), 
(default, 'Combo'), 
(default, 'Label'), 
(default, 'Textfield'), 
(default, 'Combo'), 
(default, 'Combo'); 

GRANT SELECT ON combotest.* TO 'test'@'localhost'; 

Для вашего удобства, если вы хотите, чтобы проверить это самостоятельно, я поставил все SQL команды выше.

Теперь, для моего Java кода:

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.sql.*; 
import javax.swing.*; 

public class resToComboDemo implements ActionListener { 

//JDBC Variables 
static Connection connect = null; 
static Statement statement = null; 
static ResultSet res = null; 

@SuppressWarnings("rawtypes") 
//Other Variables 
JComboBox comboBox; 
JButton submit; 
JFrame frame; 
JLabel label; 
JTextField textField; 
Container pane; 

public static void main(String[] args) throws SQLException { 
    new resToComboDemo(); 
} 

public resToComboDemo() throws SQLException { 
    try { 
     Class.forName("com.mysql.jdbc.Driver"); 
     // Setup the connection with the DB 

     connect = DriverManager 
       .getConnection("jdbc:mysql://localhost/combotest?" 
         + "user=test&password=testpw"); 

     statement = connect.createStatement(); 
     //Note: in this specific case I do realize that "order by id" is not necessary. I want it there, though. 
     res = statement.executeQuery("SELECT * FROM combotable ORDER BY id"); 

     createStuff(res); 

    } catch (Exception e) { 
     JOptionPane.showMessageDialog(null, "Error 1: "+e, "Error!", JOptionPane.ERROR_MESSAGE); 
    } finally { 
     connect.close(); 
    } 

} 

@SuppressWarnings({"rawtypes", "unchecked" }) 
public void createStuff (ResultSet res) throws SQLException { 

    frame = new JFrame("Testing dynamic gui"); 
    Dimension sD = Toolkit.getDefaultToolkit().getScreenSize(); 
    int width = sD.width; 
    int height = sD.height - 45; 
    frame.setSize(width,height); 

    pane = frame.getContentPane(); 

    pane.setLayout(new GridLayout(0, 2)); 

    while (res.next()) { 
     Object[] options = { "Pass", "Fail"}; 
     String type = res.getString("type"); 

     JLabel label = new JLabel("<html><small>"+type+"</small></html>"); 
     JLabel blank = new JLabel(" "); 
     blank.setBackground(Color.black); 
     blank.setOpaque(true); 

     if (type.equals("Label")) { 
      label.setBackground(Color.black); 
      label.setForeground(Color.white); 
      label.setOpaque(true); 
      pane.add(label); 
      pane.add(blank); 

     } else if (type.equals("Combo")) { 
      pane.add(label); 
      comboBox = new JComboBox(options); 
      pane.add(comboBox); 

     } else if (type.equals("Textfield")) { 
      pane.add(label); 
      textField = new JTextField(20); 
      pane.add(textField); 

     } 
    } 

    JLabel blank2 = new JLabel(" "); 
    pane.add(blank2); 

    submit = new JButton("Submit"); 
    submit.addActionListener(this); 
    pane.add(submit); 

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 

} 

@Override 
public void actionPerformed(ActionEvent e) { 

} 
} 

Теперь все прекрасно работает с созданием GUI здесь. Тем не менее, мне нужно уметь обрабатывать компоненты Combobox и Textfield как свои собственные отдельные объекты. Смысл, я хочу, чтобы получить пользовательский ввод от каждого другого компонента. Прямо сейчас, если я буду запрашивать информацию из текстового поля, он просто дает мне информацию из последнего текстового поля. Это прекрасно, потому что это так, как читает java. У меня нет проблем с этим.

Я просто не могу для жизни меня выяснить, как получить вход каждого компонента отдельно. Возможно, взяв результирующий набор и добавив результаты к некоторому типу массива? Я попытался это несколько раз в разных вкусах, и я не могу заставить его выйти так, как мне это нужно. Некоторые из вас попросят, чтобы я показал вам, что я пробовал ... но, честно говоря, это не стоит.

И, прежде чем кто-нибудь спросит: нет, я не буду использовать FlowLayout. :)

Любая помощь с благодарностью!

+0

Почему их не поддерживали в массиве или списке? Я бы также рекомендовал устанавливать предупреждения, а не подавлять их. –

+0

Ответ зависит. Вы заботитесь о записи 'id'? – MadProgrammer

+0

@MadProgrammer, да, идентификатор является релевантным, потому что я могу потребовать, чтобы элементы находились в определенном порядке. – user2221125

ответ

0

У вас есть ссылка на последнее текстовое поле или поле со списком, которое вы создаете, поскольку вы повторно используете переменные, которые их удерживают. Я бы поместил их в ArrayList, сохранил каждое новое текстовое поле и combbox при их создании, после чего вы сможете вернуться и получить информацию от всех из них после того, как вы закончите.

---------- (после того, как ответ OP на пункт выше)

Нет, нет «места, чтобы направить вас» - это ваш набор требований, было бы довольно примечательно, чтобы найти код, который уже существует, который сделал эту точную вещь. Java и Swing дают вам инструменты, вам нужно собрать все вместе.

Вы не показываете свою процедуру «actionPerformed», но давайте предположим об этом на минуту. Он вызывается каркасом, когда действие выполняется, и ему передается объект ActionEvent. Просматривая его методы, мы обнаруживаем, что у него есть «getSource()», поэтому он даст вам ссылку на компонент, который сгенерировал событие.

Давайте еще раз подумать о том, что у нас есть - набор компонентов в пользовательском интерфейсе, и те, которые могут генерировать события, нам интересны. Мы хотим, в этом случае, извлечь что-то из компонента, который сгенерировал событие.

Если у нас есть компонент (от actionEvent.getSource()), и мы хотим сделать что-то с ним, то мы можем, в худшем случае сделать что-то вроде следующего в actionPerformed() метод:

Component sourceComponent = actionEvent.getSource(); 
if (sourceComponent instanceof JComboBox) 
    { JComboBox sourceBox = (JComboBox) sourceComponent; 
    // get the value from the combo box here 
    } 
else if (sourceComponent instanceof JTextField) 
    { JTextField sourceTextField = (JTextField) sourceComponent; 
    // get the value from the text field here 
    } 
// or else do nothing -- our action was not one of these. 

Выполнено так, вам даже не нужно сохранять список компонентов - пользовательский интерфейс сохраняет ссылку на все из них, и вы просто используете эту ссылку, когда происходит действие actionEvent.

Теперь это не единственный или даже самый лучший или самый простой способ сделать это. Если вы хотите расширить JComboBox и JTextField со своими собственными классами, вы могли бы реализовать эти классы как интерфейс, который определил что-то вроде getValue() или getText; то вам не понадобится уродливый оператор instance of, который, как правило, может быть устранен с помощью лучшего дизайна и планирования.

+0

Возможно, я не уверен, как это сделать правильно. Как я уже сказал: это очевидное решение, но всякий раз, когда я пробовал, он просто ... не работал для меня. Можете ли вы указать мне куда-нибудь, где я могу ссылаться на что-то подобное? Если вы можете принять этот ответ. – user2221125

0

насчет опрашивая контейнера (панели), который содержит getComponents() и петлевые компоненты через компонент к югу и проверить на JComobox и JTextField сделать необходимый бросок и получить значение

только идея в случае, если вы против добавления суб-компонентов в виде списка

1

есть, вероятно, несколько способов достижения этой цели на основе того, что вы хотите сделать ...

Если вы только выполнение пакетного обновления, вы может использовать Map с ключом id строки и отображения на Component.

Таким образом, если вы хотите, чтобы сохранить значения в базу данных, вы бы просто перебирать ключевые значения Map с, извлечь Component, связанный с каждым ключом, а затем извлечь значение Component ...

я мог бы рассмотреть возможность сделать обертку interface, которая имеет простой getText метод и завернуть компонент в нем, что делаю реализацию обертки, ответственной за извлечение текста, но это только мне;)

Если вы хотите выполнить обновление, когда индивидуальный компонент обновляется, вам нужно будет заменить mappin g, так что Component будет иметь ключ и id.

Это будет означать, что, когда какое-то событие, которое вызвало бы и обновление (т.е. ActionEvent), вы могли бы извлечь source из события и посмотреть вверх id в Map на основе Component, вызвавшего событие. ..

Теперь ... откровенно говоря, я бы просто использовал JTable и создал пользовательский TableModel, который мог бы моделировать все это.

Для этого потребуется создать POJO таблицы, поддерживая id, type и value в пределах одного объекта. Это определит базовую строку в таблице.

Единственная проблема - вам нужно создать (разумно) комплекс TableCellEditor, который может принять type и вернуть соответствующий редактор для таблицы. Не невозможно, это просто дополнительная сложность, отличная от обычного использования таблицы.

Это все, что вам понадобится, доступно в одном объекте одной строки таблицы.

Посмотрите на How to use tables для получения более подробной информации

Равным образом, вы могли бы использовать подобным образом идею с Map идей выше ...

Вы также можете просто создать автономный «редактор» (простирающуюся от чего-то вроде JPanel), которые сохраняют информацию о id и type и из которого можно извлечь значение и просто сохранить список из них .... например ...

+0

Спасибо, что нашли время на этом подробном ответе! Это помогает во многих вариантах. Однако, возможно, мне не удалось объяснить, что именно я требую от своей программы. Это довольно просто. Скажем, у вас есть контрольный список, и этот контрольный список содержит два элемента. Каждому из них требуется раскрывающийся список для Pass/Fail. Рассмотрим это для примера: 1. На улице идет дождь. (Он помещается в базу данных как Combobox). Код java получает название (идет дождь) и создает JLabel. Затем создает Combobox. 2. На улице жарко. То же, что и выше. Однако мне нужно проверить оба комбо. – user2221125

+0

Затем используйте «Карта», чтобы сопоставить «id» с «компонентом». Итерации над «Картой», получение «id» и «component» проверяет все компоненты – MadProgrammer