for school I am working on a Java GUI program to store some administrative data.
Now I want to display eventdata from my DB (mysql) into a JPanel with use of a JTextField,
my problem is I can't get the size of the JTextField fixed as it always takes up a lot of place (see picture)
Picture: http://postimg.org/image/5pcklo5n1/
Here's my code, anyone some tips? (I am new to java):
public void editEvent() {
JFrame frEventEdit = new JFrame ("Event Edit Menu");
frEventEdit.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frEventEdit.setVisible(true);
frEventEdit.setSize(700, 500);
//JPanel for displaying data
JPanel pnData = new JPanel();
pnData.setLayout(new BoxLayout(pnData, BoxLayout.PAGE_AXIS));
pnData.add(Box.createRigidArea(new Dimension(0,5)));
pnData.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
pnData.setAutoscrolls(true);
Statement stmt;
try {
stmt = mySql.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name, date, time, type, address, representative FROM events " ) ;
while (rs.next() == true){
System.out.println(rs.getString("name")+" "+rs.getString("date")+" "+rs.getString("time")+" "+rs.getString("type")+" "+rs.getString("address")+" "+rs.getString("representative"));
final JTextField txtEventList = new JTextField(rs.getString("name")+" "+rs.getString("date")+" "+rs.getString("time")+" "+rs.getString("type")+" "+rs.getString("address")+" "+rs.getString("representative"));
pnData.add(txtEventList, BorderLayout.CENTER);
}
} catch (SQLException e) {
e.printStackTrace();
}
JScrollPane scroller = new JScrollPane(pnData);
frEventEdit.add(scroller);
frEventEdit.setLocationRelativeTo(null);
}
Thanks in advance
It happens because you use BoxLayout,try to use FlowLayout which is default for JPanel or another.
In next statement pnData.add(txtEventList, BorderLayout.CENTER); , BorderLayout.CENTER doesn't work, because you doesn't use BorderLayout for your panel.
For fixing size of JTextField, use constructor JTextField(int cols).
For your purposes use JTable as recommended by #AndrewThompson. Tutorial for table.
call frEventEdit.setVisible(true); at the end of construction or like next:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frEventEdit.setVisible(true);
}
});
Related
I have a JPanel which consists of a dropdown and a text field inside my JFrame. There is a button in my JFrame, when user clicks on that button, application adds new JPanel with the same components i.e. drop down and a text field. So, for this I have created a function which gets called on clicking on the button using ActionListener.
Everything works fine from GUI side but the problem is when user is done with adding JPanels and entering the values in these drop downs and text fields, it will click on Submit button. Upon clicking on Submit button, I should be able to fetch the values from all drop downs and text fields. This is a challenge, since I am using the same functions to create JPanels, I can't call its name to get the values since that will give me the last JPanel values.
Any suggestion how I should go about this? I have added the screenshot of my JFrame and the function to create the JPanel. Any help is appreciated. Thanks.
public static void AddPanel(final Container pane) {
panel1 = new JPanel();
String text = "<html><b>Property" + nooftimes + " :</b></html>";
JLabel label = new JLabel(text);
label.setPreferredSize(new Dimension(80, 30));
panel1.add(label);
panel1.add(new JLabel("Please enter the property"));
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
model.addElement("value1");
model.addElement("value2");
model.addElement("value3");
model.addElement("value4");
model.addElement("value5");
final JComboBox<String> comboBox1 = new JComboBox<String>(model);
AutoCompleteDecorator.decorate(comboBox1);
comboBox1.setPreferredSize(new Dimension(120, 22));
panel1.add(comboBox1);
final JTextField txtfield1 = new JTextField(
"Please enter your value here");
txtfield1.setPreferredSize(new Dimension(200, 22));
panel1.add(txtfield1);
txtfield1.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
txtfield1.setText("");
}
public void focusLost(FocusEvent e) {
// nothing
}
});
container.add(panel1);
nooftimes++;
frame.revalidate();
frame.validate();
frame.repaint();
}
Screenshot:
}
You could return the JPanel and store it in a List<JPanel>. When you click your submit-Button you are able to iterate through the JPanels and its Components.
public class Application {
private static List<JPanel> panels = new ArrayList<>();
private static Container someContainer = new Container();
public static void main(String[] args) {
panels.add(addPanel(someContainer));
panels.add(addPanel(someContainer));
panels.add(addPanel(someContainer));
submit();
}
public static JPanel addPanel(final Container pane) {
JPanel panel1 = new JPanel();
// shortened code
final JComboBox<String> comboBox1 = new JComboBox<String>();
panel1.add(comboBox1);
final JTextField txtfield1 = new JTextField("Please enter your value here");
txtfield1.setText(String.valueOf(Math.random()));
panel1.add(txtfield1);
return panel1;
}
private static void submit() {
for (JPanel panel : panels) {
Component[] components = panel.getComponents();
for (Component comp : components) {
// Cast comp to JComboBox / JTextField to get the values
if (comp instanceof JTextField) {
JTextField textField = (JTextField) comp;
System.out.println(textField.getText());
}
}
}
}
}
You could simply have a class (extending JPanel) with specific methods to add your components , and to get inputs from user (i.e. get the combo box selected index and text from textfield ).
Every time you add a panel, you don't call a static method, but you create an instance of this class, keeping the reference somewhere (for example adding it to an arraylist).
But you could consider a different scenario: personally i don't like to add components "on fly", you could have a component (for example another JComboBox), where user can select the number of values he needs.
You decide a default value (for example 4), so at the beginning you create 4 panels of your class, and you can use a simple array containing them.
If the user changes the number of panels, you could dispose frame and create a new one.
Of course this solution does not woork good if you want to keep inputs inserted, or if the frame construction takes a lot of time.
Here there is a screenshot of a gui i created: user can select the number of partials, when the choice changes i just recreate the panels below,containing the textfields (which are memorized in a two-dimensional array).
I am a newbie, and I have already passed some days to get the idea, but could not solve it, if anyone can help me.
I have main two JPanel in one JFrame. I have some buttons in the first panel. I have One method to add a panel to theJTabbedPane by calling another method to create that JPanels then add it to the Tab.
I want a method which will add any buttons/components to the Selected tab which I want whenever I click the button from the first panel.
How can I do this. I can post those three method's code here if anyone wish to help me. Thanks in advance.
The first code add new tabs to the JTabbedPane,
private class TabPlus implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JPanel panel = CreateSlice();
String title = "Slice " + String.valueOf(pane.getTabCount());
pane.insertTab(title, null, panel, null, pane.getTabCount() - 1);
}
}
The second code is for selecting the tabs,
private class TabSelect implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
JTabbedPane source = (JTabbedPane) e.getSource();
if (source.getSelectedComponent() != null) {
int index = source.getSelectedIndex();
System.out.print(index);
}
}
}
This creates the JPanel to be added to the JTabbedPane,
public JPanel CreateSlice() {
JPanel Slice = new JPanel();
Slice.setPreferredSize(new Dimension(550, 600));
return Slice;
}
The buttons are in another Panel with their own action.
GUI Image
You can add a panel with butttons this way:
public JPanel CreateSlice() {
JPanel Slice = new JPanel();
Slice.setPreferredSize(new Dimension(550, 600));
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton("dumpButton"));
buttonsPanel.setVisible(false);
Slice.add(buttonsPanel);
return Slice;
}
And whenever a selection occurs set the visibility of buttonsPanel to true.
I think, I found one way to do this, My index variable int index = source.getSelectedIndex(); must be public variable, then in Action event of the buttons from another tab will add component to this selected JTabbedPane.
In my case I introduced and ArrayList of panel (network_slices), and every time I am adding a panel to the JTabbedPane, it is also adding to the ArrayList. then I called the panel from the ArrayList by using the index of selected JTabbedPane. Here is the part of the code.
private class TabSelect implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
JTabbedPane source = (JTabbedPane) e.getSource();
if (source.getSelectedComponent() != null) {
index = source.getSelectedIndex();
System.out.print(index);
}
}
}
private class AddTab implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
Slice panel = new Slice();
panel.setPreferredSize(new Dimension(550, 600));
String title = "Slice " + String.valueOf(pane.getTabCount());
pane.insertTab(title, null, panel, null, pane.getTabCount() - 1);
network_slices.add(panel);
}
}
private class AddNetworkFuncitons implements ActionListener {
public void actionPerformed(ActionEvent e) {
String buttonselected = (String) e.getActionCommand();
JButton button = new JButton(buttonselected);
network_slices.get(index).add(button).setVisible(true);
System.out.print(buttonselected);
}
}
I have some code that get's data from a h2 dB and then displays it in a JScrollPane. I have added a button that should refresh the information but it isn't working.
This is my code:
Code that is used for the JPanel:
JPanel pList = new JPanel();
Component pListl = new JLabel("Here you can view players. Searching and more data will be coming soon.");
pList.add(pListl,SwingConstants.CENTER);
tabbedPane.addTab("Player List",pList);
tabbedPane.setMnemonicAt(0,KeyEvent.VK_1);
JButton ref = new JButton("Refresh");
pList.add(ref);
ref.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JScrollPane stable;
try {
stable = memlistpop(stat);
pList.remove(stable);
pList.add(stable);
JOptionPane.showMessageDialog(pList, stable);
} catch (SQLException e) {
e.printStackTrace();
}
}
});
JScrollPane stable = memlistpop(stat);
pList.add(stable);
And this is the memlistpop funcation:
public static JScrollPane memlistpop(Statement stat) throws SQLException{
ResultSet rs = stat.executeQuery("SELECT id,name,level,xp,trophycount FROM avatars");
JTable t = new JTable(DbUtils.resultSetToTableModel(rs)){;
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int row,int column){
return false;
}
};
t.setPreferredSize(new Dimension(500, 300));
JScrollPane stable = new JScrollPane (t);
stable.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
stable.setPreferredSize(new Dimension(500, 323));
//add the table to the frame
return stable;
}
Does anyone have any idea why this isn't working? Thanks!
You may add a layout manager before adding your objects.
If you want to clear the content of your panel, then:
panel.removeAll();
panel.setLayout(new BorderLayout()); // or other layout managers, such as boxlayout, etc
panel.add(myobject); // in this case, pList.add(stable);
That is what I do for myself;
Don't keep removing and adding components from a visible GUI. Instead you can just update the component in the scroll pane by using:
scrollPane.setViewportView( someComponent );
If you ever do need to remove/add components to a visible GUI, then the basic code is:
panel.remove(...);
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint();
Here is the code for a java applet in which, the combobox will retrieve content from access database and while we select an item it must display the rows of the table which have the 'composition' field as the selected combobox item. My problem is, this works fine for the first time I select it. While the result of my first selection is being shown(which is a table), if I make a second selection on the combo box, the panel becomes blank. I want it to repeatedly show corresponding outputs for successive selections also. Kindly help me diagnose the error. Thanks in advance!
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import java.util.Date;
import java.sql.*;
import java.text.*;
public class gc implements ActionListener
{
JComboBox cc=new JComboBox();
JFrame frame=new JFrame();
JTable table;
DefaultTableModel model;
String query;
int i;
JPanel panel=new JPanel();
public gc()
{
frame.setTitle("Composition Check");
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JPanel p1=new JPanel();
p1.setLayout(new FlowLayout());
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn=DriverManager.getConnection("jdbc:odbc:vasantham","","");
Statement st=conn.createStatement();
ResultSet rs=st.executeQuery("select DISTINCT composition from try");
while(rs.next())
{
cc.addItem(rs.getString("composition"));
}
conn.close();
}
catch(Exception e)
{
}
p1.add(cc);
cc.addActionListener(this);
frame.add(p1,BorderLayout.NORTH);
frame.setVisible(true);
}
public void addTable(String query)
{
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn=DriverManager.getConnection("jdbc:odbc:vasantham","","");
Statement st=conn.createStatement();
System.out.println(query);
ResultSet rs=st.executeQuery(query);
ResultSetMetaData md=rs.getMetaData();
int cols=md.getColumnCount();
model=new DefaultTableModel();
model.addColumn("Purpose");
model.addColumn("Name");
model.addColumn("Manu");
model.addColumn("Expiry");
model.addColumn("Stock");
model.addColumn("Cost");
model.addColumn("Supplier");
model.addColumn("Supplier Number");
model.addColumn("Rack");
table=new JTable(model);
String[] tabledata=new String[cols];
int i=0;
while(rs.next())
{
for(i=0;i<cols;i++)
{
tabledata[i]=rs.getObject(i+1).toString();
}
model.addRow(tabledata);
}
JScrollPane scroll = new JScrollPane(table);
panel.setLayout(new BorderLayout());
panel.add(scroll,BorderLayout.CENTER);
frame.add(panel,BorderLayout.CENTER);
conn.close();
}
catch(Exception e)
{
}
}
public void actionPerformed(ActionEvent evt)
{
String ac=(String)cc.getSelectedItem();
System.out.println(ac);
addTable("select * from try where composition='"+ac+"'");
frame.setVisible(true);
}
public static void main(String[] args)
{
new gc();
}
}
Add
panel.removeAll();
Before you add the scroll pane. This will clear the pane and make room for the next set of results...
Update
It occues to me that a better approach would be to simple replace the table's model. This lessens the risk for memory leaks, by replacing the scroll pane & table on each run.
Add a class level reference to the JTable & in your ui unit code add
table = new JTable();
JScrollPane scroll = new JScrollPane(table);
panel.setLayout(new BorderLayout());
panel.add(scroll,BorderLayout.CENTER);
frame.add(panel,BorderLayout.CENTER);
Now, in your data update code, create the new model as your are and then call
table.setModel(model);
This should be faster to update, but more importantly, takes less memory to accomplish.
As for the date format. You have two choices. You can either format the value as it comes out if the database OR you can supply you own cell renderer.
public class SQLDateTableCellRenderer extends DefauktTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if (value instanceof java.sql.Date) {
value = new SimpleDateFormat("dd/MM/yyyy").format(value);
}
retrun super.getTableCellRenderer(...);
}
}
Forgive the short hand, I'm on my iPad. It would be better to use a static or class reference to the date format, but that would require meto type more ;)
You could then set this as the default renderer on the JTable. This saves you the need to know which columns need a SQL date formatted.
table.setDefaultRenderer(java.sql.Date, new SQLDateTableCellRenderer());
This, of course, means tat rather then converting the objects to strings when you extract them from the database, you will simply want to extract the objects directly
tabledata[i]=rs.getObject(i+1);
Make sure you convert the tabledata to a Object[] array instead of Strings.
I have a JTable in a JPanel (called cur_panel) of a JTabbedPane which is fetching contents from a MySQL database. Now I want to be able to refresh the table whenever I make changes using the options in other pane of JTabbedPane. I got around this problem by destroying cur_panel and then again constructing it so that it could fetch refreshed data from the database.
Can someone suggest me a better way getting around it? Like if I could fetch only the new/modified data and withouut having destroy and then reconstruct the JPanel.
You're right - you shouldn't need to re-construct the JPanel. Indeed, you shouldn't even need to reconstruct the JTable, or possibly even the TableModel. (Also, you might want to do some reading about the Model-View-Controller design pattern)
Instead, you should be resetting the data in the TableModel. I think this should cause the JTable to be repainted. If not, you could call:
table.tableChanged(new TableModelEvent(tableModel));
Alternatively, if you feel it's better to construct a new TableModel with the new data:
table.setModel(newTableModel);
Here's an SSCCE of a JTable that is updated by something else... I've replaced the database connection with input from a JTextField, but it should give you the idea:
public class TableTest {
public static void main(String[] args) {
JFrame frame = new JFrame("Table Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextField text = new JTextField("Editable Text");
final TableModel model = new DefaultTableModel(new String[]{"Text"},1);
model.setValueAt(text.getText(), 0, 0);
text.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
model.setValueAt(text.getText(), 0, 0);
}
});
JTable table = new JTable(model);
JPanel panel = new JPanel(new BorderLayout());
panel.add(text, BorderLayout.NORTH);
panel.add(new JScrollPane(table), BorderLayout.SOUTH);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
}