I have created a JFrame in Eclipse, and also placed a JList in the frame using the Swing design option. Eclipse puts the list in a JPanel. Next to the list, there are a few text fields(ID, name, etc.). Once the user fills the fields, and clicks 'Add', the information gets stored in a SQLite JDBC table. However, when the user clicks add, I also want the JList to update itself and display the new record in the list. The list only refreshes only when I restart the program. I have tried to revalidate() and repaint the panel created by Eclipse after the record is added to the database, as well as tried to revalidate() and repaint the list.
Register and Listener implementation . Try this code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyFrame extends JFrame implements ActionListener {
private JButton button = new JButton("Click me!");
private DefaultListModel<String> listModel = new DefaultListModel<String>();
private JList<String> list = new JList<String>(listModel);
private int counter = 1;
public MyFrame() {
setTitle("Test Updates");
JTabbedPane tabs = new JTabbedPane();
add(tabs, BorderLayout.CENTER);
JPanel panel = new JPanel();
panel.add(list);
tabs.add("Selections", panel);
panel = new JPanel();
button.addActionListener(this);
panel.add(button);
tabs.add("Options", panel);
pack();
}
#Override
public void actionPerformed(final ActionEvent event) {
if (button.equals(event.getSource())) {
listModel.addElement("Item " + counter++);
}
}
/* Test it! */
public static void main(String[] args) {
final MyFrame frame = new MyFrame();
frame.addWindowListener(new WindowAdapter(){
#Override public void windowClosing(final WindowEvent e) {
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
});
frame.setVisible(true);
}
}
Related
package database;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.SwingUtilities;
public class Application {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new ApplicationFrame("Application");
frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
public class ApplicationFrame extends JFrame {
private CompaniesPanel companiesPanel;
public ApplicationFrame(String title) {
super(title);
setLayout(new BorderLayout());
JMenuBar menuBar = new MenuBar("Menu");
Container container = getContentPane();
container.add(menuBar, BorderLayout.NORTH);
}
}
public class MenuBar extends JMenuBar {
public MenuBar(String title) {
super();
JMenu menuFile = new JMenu("File");
add(menuFile);
JMenu menuOpen = new JMenu("Open");
menuFile.add(menuOpen);
JMenuItem menuItemCompanies = new JMenuItem("Companies");
menuOpen.add(menuItemCompanies);
menuItemCompanies.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// In here I would like to take a CompaniesPanel and insert
// it into
// an ApplicationFrame if the Companies button is pressed on
// menu
}
});
}
}
public class CompaniesPanel extends JPanel {
public CompaniesPanel() {
Dimension size = getPreferredSize();
size.width = 250;
setPreferredSize(size);
setBorder(BorderFactory.createTitledBorder("Company Names"));
setLayout(new GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
}
}
}
I just want my application to open up that menu with the rest being blank, and open up the CompaniesPanel when Companies is pressed from the drop down menu. Is this possible without opening up another jFrame?
container.add(menuBar, BorderLayout.NORTH);
Frist of all that is not how you add a menu to the frame. A frame has a special area reserved for the menu bar.
Instead you just use:
setJMenuBar( menuBar );
Read the section from the Swing tutorial on How to Use Menus for more information and working examples.
As already mentioned a CardLayout would be a good choice. By adding two panels (one empty, and one for the companines) the preferred size of the layout will be determined by your companies panel so the frame size does not change when you display the companies panel.
The Swing tutorial also has a section on How so Use CardLayout with working examples to get your started.
Keep a reference to the Swing tutorial handy for all the Swing basics.
The imports are okay, I just want to print out the result in the JTextArea in the second JFrame after the search button is clicked.
When I run this program, my whole JFrame panel shows a huge full screen button named 'search'.
import java.awt.event.*;
import javax.swing.*;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
private static final String DB_PATH = "C:/Users/Abed/Documents/Neo4j/Movies2.graphdb";
public static GraphDatabaseService graphDB;
public static void main(String[] args) throws Exception {
showFrame();
}
public static void showFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 500);
final JTextField actorInput = new JTextField(10);
final JTextField genreInput = new JTextField(10);
frame.getContentPane().add(actorInput);
frame.getContentPane().add(genreInput);
JButton submit = new JButton("Search");
submit.setSize(5, 5);
frame.getContentPane().add(submit);
submit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
graphDB = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
Transaction tx = graphDB.beginTx();
String actor = actorInput.getText();
String genre = genreInput.getText();
final String query;
query = "MATCH (Movie {genre:'"
+ genre
+ "'})<-[:ACTS_IN]-(Person {name:'"
+ actor
+ "'}) "
+ "RETURN Person.name, Movie.genre, COUNT(Movie.title) AS cnt "
+ "ORDER BY cnt DESC " + "LIMIT 100 ";
try {
JFrame frame2 = new JFrame();
frame2.setVisible(true);
JTextArea ta = new JTextArea();
ta.setLineWrap(true);
frame2.add(ta);
ExecutionEngine engine = new ExecutionEngine(graphDB,
StringLogger.SYSTEM);
ExecutionResult result = engine.execute(query);
System.out.println(result);
String resultArea = result.dumpToString();
ta.setText(resultArea);
tx.success();
} finally {
tx.close();
graphDB.shutdown();
}
}
});
}
}
Issues and suggestions:
JFrame contentPanes use BorderLayout by default.
If you add anything to a BorderLayout-using container without specifying where to place it, it will go by default to the BorderLayout.CENTER position.
Something in the BorderLayout.CENTER position will cover up anything previously added there.
You really don't want your GUI to have more than one JFrame. A separate dialog window perhaps, or a swapping of views via CardLayout perhaps, but not more than one main program window. Please check out The Use of Multiple JFrames, Good/Bad Practice?.
You're calling setVisible(true) on your JFrame before adding all components to it, and this can lead to non-visualization or inaccurate visualization of your GUI. Call setVisible(true) after adding all components that you're adding initially.
Why does your class extend JFrame when it's never used as a JFrame?
Your critical code is contained all within a static method losing all the advantages of Java's use of the object-oriented programming paradigm. Myself, when I create a new project, I concentrate on creating classes first, and then GUI's second.
Solution for the button covering up your GUI -- read up on and use layout managers in a smart and pleasing way to create smart and pleasing GUI's. The tutorials can be found here:
Swing Info
Laying out Components in a Container
For example:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class MyMain extends JPanel {
private JTextField actorInput = new JTextField(10);
private JTextField genreInput = new JTextField(10);
public MyMain() {
// JPanels use FlowLayout by default
add(actorInput);
add(genreInput);
add(new JButton(new SubmitAction("Submit")));
add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
}
private class SubmitAction extends AbstractAction {
public SubmitAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent evt) {
String actor = actorInput.getText();
String genre = genreInput.getText();
// call database code here in a background thread
// show a dialog with information
String textToDisplay = "Text to display\n";
textToDisplay += "Actor: " + actor + "\n";
textToDisplay += "Genre: " + genre + "\n";
InfoDialogPanel dlgPanel = new InfoDialogPanel();
dlgPanel.textAreaSetText(textToDisplay);
Window window = SwingUtilities.getWindowAncestor(MyMain.this);
JDialog modalDialog = new JDialog(window, "Dialog", ModalityType.APPLICATION_MODAL);
modalDialog.getContentPane().add(dlgPanel);
modalDialog.pack();
modalDialog.setLocationByPlatform(true);
modalDialog.setVisible(true);
}
}
private static void createAndShowGui() {
MyMain mainPanel = new MyMain();
JFrame frame = new JFrame("MyMain");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class InfoDialogPanel extends JPanel {
private JTextArea textArea = new JTextArea(10, 20);
private JScrollPane scrollPane = new JScrollPane(textArea);
public InfoDialogPanel() {
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
public void textAreaSetText(String text) {
textArea.setText(text);
}
public void textAreaAppend(String text) {
textArea.append(text);
}
}
class ExitAction extends AbstractAction {
public ExitAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent evt) {
Component component = (Component) evt.getSource();
Window win = SwingUtilities.getWindowAncestor(component);
win.dispose();
}
}
I have 2 frames, the first frame has the nothing more and a button, which leads to another frame which will have all the components, like tabs which have more components.
The code I am using is:
button_1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
JFrame Frame_2 = new JFrame();
Frame_1.setVisible(false);
Frame_2.setVisible(true);
}
});
this is creating a new separate frame , but i want to create new JFrame over existing JFrame
update
#VinceEmigh +1
Thanks for the detail custom solution. It shows that someone is really willing to help, I am a self learner , started just 3 months ago so your code is bit difficult to understand, but the idea of using cardlayout did the work and i came up with a solution.
JFrame guiFrame = new JFrame();
CardLayout cards;
JPanel cardPane;
JButton B_1 = new JButton("Next Card");
B_1.setActionCommand("Next Card");
B_1.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
cards.next(cardPane);
}
});
cards = new CardLayout();
cardPane = new JPanel();
cardPane.setLayout(cards);
cards.show(cardPane, "Main");
JPanel Card_1 = new JPanel();
JLabel background_1 = new JLabel(new ImageIcon("C:\\Users\\ME\\Desktop\\Back1.jpg"));
Card_1.add(background_1);
Card_1.add(B_1);
JPanel Card_2 = new JPanel();
JLabel background_2 = new JLabel(new ImageIcon("C:\\Users\\ME\\Desktop\\Back2.jpg"));
Card_2.add(background_2);
cardPane.add(Card_1, "Main");
cardPane.add(Card_2, "Sub");
You shouldnt use 2 frames. You should use 1 frame, then switch between panels in the frame using CardLayout. Unless you're referring to nesting a frame within a frame, creating 2 different frames for 1 applicarion is typically bad practice, and should be avoided if possible.
Set your frames layout to CardLayout, add 2 panels to your frame. One panel contains the button, the other has the components.
When your button event triggers throuhh an actionlistener, switch out the panels using the cardlayout you put for the frames layout.
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class App extends JFrame {
private CardLayout cl = new CardLayout();
private JPanel firstPanel = new FirstPanel();
private JPanel secondPanel = new SecondPanel();
public App() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setLayout(cl);
add(firstPanel, "first");
add(secondPanel, "second");
setLocationRelativeTo(null);
setVisible(true);
}
public void switchPanel(String name) {
cl.show(getContentPane(), name);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
App app = new App();
}
});
}
class FirstPanel extends JPanel implements ActionListener {
private JButton button = new JButton("Button");
public FirstPanel() {
button.addActionListener(this);
add(button);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button) {
switchPanel("second");
}
}
}
class SecondPanel extends JPanel { }
}
I am trying to listen to mouse events coming from both a JLabel and a JTextField. However, I am only able to listen to mouse events from JLabel, but not JTextField.
Consider this code:
class FieldPanel extends JPanel{
JLabel label;
JTextField text;
public FieldPanel(){
label = new JLabel("This is a test label");
text = new JTextField("This is a test field");
add(label);
add(text);
}
}
class OuterPanel extends JPanel{
FieldPanel fieldPanel;
public OuterPanel(){
fieldPanel = new FieldPanel();
fieldPanel.addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent event) {
System.out.println("Mouse pressed !!");
}
});
add(fieldPanel);
}
}
public class UITest{
public static void main (String args[]){
JFrame frame = new JFrame();
OuterPanel outerPanel = new OuterPanel();
frame.getContentPane().add(outerPanel);
frame.pack();
frame.setVisible(true);
}
}
The 'Mouse Pressed !!' message is displayed when I click on the JLabel. However, it does not get displayed when I click on the JTextField. Why is this the case?
Thanks!
I think this is an interesting question which kinda stomp on the finding accidentally. I will explain using the snippet code below.
class FieldPanel extends JPanel
{
//JLabel label;
JTextField text;
public FieldPanel()
{
//label = new JLabel("This is a test label");
text = new JTextField("This is a test field");
//add(label);
add(text);
}
}
when you run the code with the changes above, what we expect the output only the text field right? Then if you click on the area near to the textfield outside region, check in your console output, it actually print out Mouse pressed !!
So I went a little deeper to study into JTextField, it actually consist of the JTextField and JTextComponent. When you called the constructor new JTextField("This is a test field");, the text is actually set into the JTextComponent and not JTextField and I guess that is why when you click the text, it does not trigger the mousePressed event but it trigger only the JTextField only.
Below is my full code. If you want the text field to aware of the mouse pressed, consider implements MouseAdapter() in your FieldPanel class and add addMouseListener(this) for text and label.
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class MyMouseEvent extends JPanel
{
public MyMouseEvent()
{
FieldPanel fieldPanel;
fieldPanel = new FieldPanel();
fieldPanel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent event)
{
System.out.println("Mouse pressed !!");
}
});
add(fieldPanel);
}
class FieldPanel extends JPanel
{
//JLabel label;
JTextField text;
public FieldPanel()
{
//label = new JLabel("This is a test label");
text = new JTextField("This is a test field");
//add(label);
add(text);
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyMouseEvent evt = new MyMouseEvent();
evt.setOpaque(true);
frame.setContentPane(evt);
frame.pack();
frame.setVisible(true);
}
public static void main (String args[])
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run()
{
createAndShowGUI();
}
});
}
}
Thanks for all the answers.
I found some sort of workaround. I am changing my code so that I listen directly to the JTextField component, as opposed to listening to the panel.
I'm creating a very simple program.
I have created this classes :
MainJframeClass, JDesktopPaneClass, JinternalFrameClass1 and JinternalFrameClass2.
what ive done is that i instantiated my jdesktoppaneclass and named it desktoppane1 and i added it to the MainJframeclass. i have also instantiated the 2 jinternalframes and named it internal1 and internal2. Now, i have button in mainjframeclass that when i press, i add the internal1 to desktoppane1. what my problem now is how to add the internal2 to desktoppane1 using a button placed somewhere in internal1. i know that why could i just add another button to desktoppane1 and add the internal2. but i have done it already, i just want to solve this problem. if you can help me please. sorry for my english by the way.
It's simply a matter of references. The code that adds something to the JDesktopPane must have a reference to it, and so you will need to pass that reference into the class that needs it say via either a constructor parameter or a method parameter.
Edit 1
For example:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class ReferenceExample extends JPanel {
private JDesktopPane desktop = new JDesktopPane();
private Random random = new Random();
public ReferenceExample() {
JButton addInternalFrameBtn = new JButton("Add Internal Frame");
addInternalFrameBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
addInternalFrame();
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(addInternalFrameBtn);
setPreferredSize(new Dimension(600, 450));
setLayout(new BorderLayout());
add(new JScrollPane(desktop), BorderLayout.CENTER);
add(btnPanel, BorderLayout.SOUTH);
}
public void addInternalFrame() {
MyInternalFrame intFrame = new MyInternalFrame(ReferenceExample.this);
int x = random.nextInt(getWidth() - intFrame.getPreferredSize().width);
int y = random.nextInt(getHeight() - intFrame.getPreferredSize().height);
intFrame.setLocation(x, y);
desktop.add(intFrame);
intFrame.setVisible(true);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Reference Eg");
frame.getContentPane().add(new ReferenceExample());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class MyInternalFrame extends JInternalFrame {
// pass in the reference in the constructor
public MyInternalFrame(final ReferenceExample refEg) {
setPreferredSize(new Dimension(200, 200));
setClosable(true);
JButton addInternalFrameBtn = new JButton("Add Internal Frame");
addInternalFrameBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// use the reference here
refEg.addInternalFrame();
}
});
JPanel panel = new JPanel();
panel.add(addInternalFrameBtn);
getContentPane().add(panel);
pack();
}
}
how to add the internal2 to desktoppane1 using a button placed somewhere in internal1.
In the ActionListener added to your button you can use code like the following to get a reference to the desktop pane:
Container container = SwingUtilities.getAncestorOfClass(JDesktopPane.class, (Component)event.getSource());
if (container != null)
{
JDesktopPane desktop = (JDesktopPane)container;
JInternalFrame frame = new JInternalFrame(...);
desktop.add( frame );
}