I try to initiate a "JTable", I added all my elements through the form designer and initiated them in the main function of my GUI.
The table is placed inside a "JScrollPanel" and used a "DefaultTableModel" to add the headers and rows.
Whatever I did, I can't make the table to display headers or rows.
What am I missing here?
class Controls extends JPanel{
private JButton compileButton;
private JPanel controls;
private JTabbedPane tabbedPane1;
private JButton insertButton;
private JTable insertedFilesTable;
private JScrollPane insertedFilesViewport;
private JPanel minify;
private JFileChooser insertChooser;
public Controls () {
insertChooser = new JFileChooser();
compileButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
initCompile();
}
});
insertButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
buttonActionPerformed(e);
}
});
}
public void main () {
JFrame frame = new JFrame("Controls");
frame.setLayout(new SpringLayout());
frame.setContentPane(new Controls().controls);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel();
model.addColumn("Files");
model.addColumn("Status");
insertedFilesTable = new JTable(model);
insertedFilesViewport = new JScrollPane(insertedFilesTable);
insertedFilesViewport.setViewportView(insertedFilesTable);
insertedFilesTable.setFillsViewportHeight(true);
String[] data = {"test","test"};
model.addRow(data);
frame.add(insertedFilesViewport);
frame.setSize(500,500);
frame.setVisible(true);
}
private void buttonActionPerformed(ActionEvent evt) {
insertChooser.showSaveDialog(this);
}
}
frame.setLayout(new SpringLayout());
....
frame.add(insertedFilesViewport);
Don't change the layout of the frame to a SpringLayout. There is no reason to do this.
The reason you don't see the scroll pane containing the table is because you didn't use any constraints for the add(...) method. Read the section from the Swing tutorial on How to Use SpringLayout to see how complex the constraints are for adding components.
If you leave the layout as the default BorderLayout, then the component will be added to the CENTER of the BorderLayout by default. The above tutorial also has a section on How to Use BorderLayout you should read.
Related
I set JTextField "rfid" to setEnabled(false) in MainGUI class and created method setRfidEnabled to be able to enable textfield from another class called CardLayout.
When I try to call it from CardLayout by button event listener it does nothing, I mean to textfield, because System.out.print("LOL"); works fine. MainGUI contains JFrame and by button calls another JFrame in CardLayout class.
When I initialize MainGUI class, it has Thread[Thread-2,6,main], but when I call CardLayout it becomes Thread[AWT-EventQueue-0,6,main], same as CardLayout itself. I tried to make "rfid" volatile, no success.
---Edited code---
MainGUI:
public class MainGUI {
JTextField rfid;
JButton button;
final JFrame frame;
final JPanel pane;
LayoutChanger layout = new LayoutChanger();
public MainGUI() {
rfid = new JTextField("", 10);
button = new JButton("CardLayoutSwitch");
frame = new JFrame("Main GUI Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout(5,5));
pane = new JPanel(new GridLayout(5, 5));
frame.add(pane,BorderLayout.CENTER);
pane.add(rfid);
pane.add(button);
rfid.setEnabled(false);
button.setEnabled(true);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent e){
layout.changeLayout(1);
}
});
}
public void setRfidEnabled() {
System.out.println("LOL");
rfid.setEnabled(true);
button.setEnabled(false);
}
}
LayoutChanger class:
public class LayoutChanger {
public static void main(String[] args) {
MainGUI gui = new MainGUI();
}
public void changeLayout(int i){
if (i == 1) {
CardLayout card = new CardLayout();
}
}
}
CardLayout class:
public class CardLayout {
JFrame frame;
JButton manual;
final JPanel pane;
MainGUI gui = new MainGUI();
public CardLayout() {
manual = new JButton("UID MANUAL");
frame = new JFrame("Card Scan Panel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLayout(new BorderLayout(5, 5));
pane = new JPanel(new BorderLayout(5, 5));
manual.setPreferredSize(new Dimension(50, 25));
frame.add(pane, BorderLayout.CENTER);
pane.add(manual);
frame.pack();
frame.setVisible(true);
frame.setLocationRelativeTo(null);
manual.addActionListener(new ActionListener() {
#Override
public void actionPerformed (ActionEvent e){
gui.setRfidEnabled();
}
});
}
}
As stated in the comments above by #matt
Every time you click on manual button, you're creating a new MainGUI().
You need to create a single instance, either in your constructor or in the ActionListener and ask if you already have an instance of it (i.e. a Singleton) and use it.
If you decide to use the first one, declare gui as a global variable:
MainGUI gui = new MainGUI();
And on your ActionListener have it changed as:
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(currentThread());
gui.setRfidEnabled();
//frame.dispose();
}
Then you have a single instance of it.
Also as stated by #Sergiy you don't really need all those threads
Here are some examples on how to use ActionListeners:
I'm trying to make a button to count characters in a text field
AppletViewer bugged and trying to involve a timer
Calculator returns 0.0 to all questions asked
Java - My action event doesn't work
Drawing shapes on a JForm java
Animated Sprites with Java Swing This one includes a Timer (Another thread that handles the animation but doesn't block the EDT)
As you can see in all the above examples, none of them required another Thread to handle the actions, the one that uses a thread is only for performing the animation and not to react to user clicks.
Recommended tutorial: How to use Actions
Hi I am trying to create Scroll Bar for my JFrame. I created JPanel object and set components into JPanel. Then created a JScrollPane object for the panel. Then add the ScrollPane object to JFrame. I am not seeing any scrollbar. Also I am wondering if there is a option in JPanel that would resize the object inside Jpanel automatically according to the zoom level of the JPanel. Any help would be highly appreciated.
public class xmlottgui {
private JPanel Container;
private JFrame frmCreateXml;
private JTextField titlename;
private JLabel lbltitlename;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
xmlottgui window = new xmlottgui();
window.frmCreateXml.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public xmlottgui() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
Container = new JPanel();
Container.setLayout(null);
//JScrollPane pane=new JScrollPane(Container,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
frmCreateXml = new JFrame();
frmCreateXml.setTitle("Create XML");
frmCreateXml.setBounds(100, 100, 1000, 1200);
frmCreateXml.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmCreateXml.getContentPane().setLayout(null);
//Create MenuBar
JMenuBar menuBar = new JMenuBar();
Container.add(menuBar);
JMenu mnFile = new JMenu("File");
menuBar.add(mnFile);
JMenuItem mntmImportFromCsv = new JMenuItem("Import From Excel File");
//Add menu item Exit
JMenuItem mntmexit = new JMenuItem("Exit");
mntmexit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
mnFile.add(mntmexit);
showform();
JScrollPane pane=new JScrollPane(Container,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
pane.setLayout(null);
frmCreateXml.setContentPane(pane);
frmCreateXml.getContentPane().add(pane);
}
private void showform(){
titlename = new JTextField();
titlename.setBounds(164, 27, 749, 26);
Container.add(titlename);
titlename.setColumns(10);
lbltitlename = new JLabel("Title Name");
lbltitlename.setBackground(Color.GRAY);
lbltitlename.setBounds(22, 1000, 90, 16);
Container.add(lbltitlename);
}
This:
pane.setLayout(null);
Will completely disable your JScrollPane and prevent it from working as it will prevent the JScrollPane from displaying and manipulating its view port properly. JScrollPanes have there own very special layout manager, one you never want to muck with unless you are very clever and know what you're doing. As a general rule you should almost never use null layouts.
Also this is not correct:
frmCreateXml.setContentPane(pane);
frmCreateXml.getContentPane().add(pane);
You make pane the contentPane and then add pane to itself.
AND THIS is messing you up:
frmCreateXml.getContentPane().setLayout(null);
You will want to learn about and use the layout managers as it will make your life much easier.
I'm changing my JFrame's content pane and simply want to focus a JTextField in the new panel. So I'm doing this:
JPanel pNew = new JPanel();
frame.setContentPane(pNew);
frame.revalidate();
frame.repaint();
public JPanel() {
...
tf.requestFocusInWindow();
}
When I use setVisible(false) and setVisible(true) instead of revalidating and repainting my frame, I get my wished effect, but that's not the way I want to do it.
What else happens in setVisible() but revalidating and repainting?
A CardLayout is typically used to swap panels.
However, even the default implementation of CardLayout does not set focus on the panel when it is swapped. However you can check out Card Layout Focus which will allow you to request focus on the panel when it is switched.
The requestFocusInWindow() method only works on a component that is displayed in a visible frame. So you can't invoke the method in the constructor of the class.
You could use the RequestFocsListener found in Dialog Focus. It will wait until the panel is added to a visible GUI before generating the event.
I got it to work simply by putting the requestFocusInWindow() call in the button's action listener. As camickr mentioned the call needs to be made after the constructor. Here's an example program showing how I got it to work. Hope it helps!
public class PanelRevalidate {
public JFrame frame;
public MyPanel panel1, panel2;
public PanelRevalidate() {
frame = new JFrame();
panel1 = new MyPanel(1);
panel2 = new MyPanel(2);
frame.setContentPane(panel1);
panel1.getSwap().addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
frame.setContentPane(panel2);
frame.revalidate();
panel2.getTextField().requestFocusInWindow();
}
});
panel2.getSwap().addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
frame.setContentPane(panel1);
frame.revalidate();
panel1.getTextField().requestFocusInWindow();
}
});
frame.setVisible(true);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
new PanelRevalidate();
}
});
}
}
And the MyPanel class:
public class MyPanel extends JPanel {
public JTextField tf;
public JButton swap;
public JLabel panel_label;
public MyPanel(int n) {
tf = new JTextField(25);
swap = new JButton("Swap");
panel_label = new JLabel("panel " + n);
add(tf);
add(swap);
add(panel_label);
}
public JButton getSwap() {
return swap;
}
public JTextField getTextField() {
return tf;
}
}
I'm fairly new to Java Swing and I'm running into a few problems.
As a side question, when making a fairly large Java Swing Application, what is the best way to split up code?
In my case I want to have an application that has a layout just as Microsoft Word where there is a JToolBar filled with buttons and a main JPanel where changes are made based on the buttons pressed in the Tool Bar.
So as shown in the code below, I have a JFrame and I call the MainPanel class in order to create a panel and add a ToolBar with a button. When the button is pressed it adds a button to the panel. The problem comes when you click the button nothing shows up until you resize the window(in my case I simply manually drag the screen to make it larger).
public class Main {
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("MathMaker");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create the menu bar. Make it have a green background.
//MainToolBar mainTB = new MainToolBar();
MainPanel mainPanel = new MainPanel();
frame.getContentPane().add(mainPanel.getGUI(), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
public class MainPanel implements ActionListener{
JPanel mPanel;
JToolBar mToolBar;
JButton addQuestion;
public MainPanel() {
mPanel = new JPanel(new BorderLayout());
mToolBar = new JToolBar();
addQuestion = new JButton("test");
addQuestion.addActionListener(this);
mPanel.setLayout(new BorderLayout());
mPanel.setBackground(new Color(248, 213, 131));
mPanel.setPreferredSize(new Dimension(200, 180));
mToolBar.add(addQuestion);
mPanel.add(mToolBar, BorderLayout.PAGE_START);
}
public JComponent getGUI()
{
return mPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
JButton temp = new JButton("temp");
mPanel.add(temp);
}
}
You should revalidate your panel
#Override
public void actionPerformed(ActionEvent e) {
JButton temp = new JButton("temp");
mPanel.add(temp);
mPanel.revalidate();
mPanel.repaint();
}
I believe you need to call revalidate() and repaint() to see the changes, here is a similar question here
The problem here is the panel is not repainted automatically.. When you resize the panel Java repaints the panel on the screen. Try repainting the panel everytime any button to modify the panel is clicked..
Just call the validate() and repaint() method with the panel
I have created a frame in Java which has some textfields and buttons in it. Assuming that user wants more textfields (for example to add more data), I want to put a button and when a user clicks the button, then a new textfield should appear. then user can fill data in it and again by clicking that button another textfield should appear.
How can I do this ? What code I need to write for the button to show more and more text fields by clicking button?
Thank you !
It would be wise that instead of adding components to your JFrame directly, you add them to a JPanel. Though related to your problem, have a look at this small example, hopefully might be able to give you some hint, else ask me what is out of bounds.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class JFrameExample
{
private JFrame frame;
private JButton button;
private JTextField tfield;
private String nameTField;
private int count;
public JFrameExample()
{
nameTField = "tField";
count = 0;
}
private void displayGUI()
{
frame = new JFrame("JFrame Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(0, 1, 2, 2));
button = new JButton("Add JTextField");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent ae)
{
tfield = new JTextField();
tfield.setName(nameTField + count);
count++;
frame.add(tfield);
frame.revalidate(); // For JDK 1.7 or above.
//frame.getContentPane().revalidate(); // For JDK 1.6 or below.
frame.repaint();
}
});
frame.add(button);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new JFrameExample().displayGUI();
}
});
}
}
Supposing that you have a main container called panel and a button variable button which is already added to panel, you can do:
// handle the button action event
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// create the new text field
JTextField newTextField = new JTextField();
// add it to the container
panel.add(newTextField);
panel.validate();
panel.repaint();
}
});
When adding the new text field, you may need to mention some layout related characteristics, depending on the layout manager you are using (for instance if you use GridBagLayout, you will need to specify the constraints).