JAVA cardLayout. how to call a card from different classes - java

i have a program with a frame that contains a main panel with the cardlayout layout, and i want it to display different cards/panel.
In my case i'm really struggling to call a new card from a button action listener.
I want a new card to appear after i click on a button but none of the codes i put in my action listener displayed the card i wanted.
I know my actionListener work because i did a println inside.
here's my code. i got rid of anything that was unnecessary so it's easier to read. Thanks for the help!
i'll take all advices about code structuration
the mainFrame :
public class MainFrame extends JFrame{
final static String CONNEXION_VIEW = "connexionView";
final static String CONNEXION_FAILED_VIEW = "connexionRefusee";
public MainFrame()
{
super();
initialize();
}
private void initialize()
{
getMainPanel();
add(getMainPanel());
}
CardLayout cardLayout;
public CardLayout getCardLayout()
{
if (cardLayout == null)
{
cardLayout = new CardLayout();
}
return cardLayout;
}
JPanel mainPanel;
public JPanel getMainPanel()
{
if (mainPanel == null)
{
mainPanel = new JPanel();
mainPanel.setLayout(getCardLayout());
mainPanel.add(CONNEXION_VIEW, getConnexionView());
mainPanel.add(CONNEXION_FAILED_VIEW, getConnexionFailedView());
}
return mainPanel;
}
ConnexionView connexionView;
protected ConnexionView getConnexionView()
{
if (connexionView == null)
{
connexionView = new ConnexionView();
}
return connexionView;
}
ConnexionFailedView connexionFailedView;
protected ConnexionFailedView getConnexionFailedView()
{
if (connexionFailedView == null)
{
connexionFailedView = new ConnexionFailedView();
}
return connexionFailedView;
}
the connexion view, the one with the button to click with the action listener where i want to put my code
public class ConnexionView extends JPanel{
GridBagLayout gbl = new GridBagLayout();
private JButton btnConnexion;
Dimension dimensionBouton = new Dimension(170, 30);
public ConnexionView()
{
super();
initialise();
}
private void initialise()
{
setLayout(gbl);
GridBagConstraints gbcbtnConnexion = new GridBagConstraints();
gbcbtnConnexion.gridwidth = GridBagConstraints.REMAINDER;
gbcbtnConnexion.gridheight = GridBagConstraints.REMAINDER;
gbcbtnConnexion.gridx = 1;
gbcbtnConnexion.gridy = 2;
add(getBtnConnexion(), gbcbtnConnexion);
}
private JButton getBtnConnexion()
{
if (btnConnexion == null)
{
btnConnexion = new JButton("Connexion");
btnConnexion.setPreferredSize(dimensionBouton);
btnConnexion.setMinimumSize(dimensionBouton);
btnConnexion.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
/////code to display the connexion_Failed_View
System.out.println("test");
}
});
}
return btnConnexion;
}
}
and the connexion failed view, the one i want to display after the button is clicked
public class ConnexionFailedView extends JPanel{
public ConnexionFailedView()
{
super();
initialise();
}
private void initialise()
{
setBackground(Color.YELLOW);
}
thanks in advance

You will need to keep the component in your Button somehow, so you can access it.
class ConnexionView {
private JComponent mainPanel;
public ConnexionView(JComponent mp) { mainPanel = mp; }
}
Obviously, that means the MainFrame needs to pass it then.
Now, the listener can do
// it would be cleaner if you passed the layout in the constructor as well
CardLayout cl = (CardLayout) mainPanel.getLayoutManager();
cl.show(mainPanel, MainFrame.CONNEXION_FAILED_VIEW);

Related

Swing - JList contents disappear randomly on dynamic update

It has been a while since the last time I did Swing programming, and today I'm getting back to it. I have a simple JList which is backed by DefaultListModel. I also have a JButton which will show a JFileChooser. When a directory is selected, the JList is supposed to be populated with the file names under the selected directory.
What I found is that occasionally (actually it happens randomly quite often), the list wont be updated until I click on the (seemingly blank) list. I thought by using DefaultListModel, I can just call addElement() which will trigger the fireIntervalAdded (which should repaint the list, the container, etc) ? ALso, I believe the actionPerformed() method is invoked inside the EDT, so I should just be able to update the DefaultListModel. Anyway.... I have also tried calling revalidate() and repaint() on the list, the container, etc without any success either.
Secondly, when the list already has some items in it, clicking the button (which triggers the filechooser to be shown) will clear up the JList entries (without calling clear() on the model).
The source code is available at:
https://github.com/alexwibowo/spider
Here is an abstract of the code (hopefully it is sufficient)
package org.github.alexwibowo.spider.gui;
import com.jgoodies.forms.factories.CC;
import com.jgoodies.forms.layout.FormLayout;
import javax.swing.*;
public class MainPanel extends JPanel {
public MainPanel() {
initComponents();
}
private void initComponents() {
toolBar1 = new JToolBar();
openFolderButton = new JButton();
splitPane1 = new JSplitPane();
scrollPane1 = new JScrollPane();
fileList = new JList();
//======== this ========
setLayout(new FormLayout(
"default:grow",
"default, $lgap, fill:default:grow"));
//======== toolBar1 ========
{
toolBar1.setFloatable(false);
//---- openFolderButton ----
openFolderButton.setIcon(UIManager.getIcon("Tree.openIcon"));
openFolderButton.setBorder(new EmptyBorder(5, 5, 5, 5));
toolBar1.add(openFolderButton);
}
add(toolBar1, CC.xy(1, 1));
//======== splitPane1 ========
{
//======== scrollPane1 ========
{
//---- fileList ----
fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scrollPane1.setViewportView(fileList);
}
splitPane1.setLeftComponent(scrollPane1);
}
add(splitPane1, CC.xy(1, 3));
}
protected JToolBar toolBar1;
protected JButton openFolderButton;
protected JSplitPane splitPane1;
protected JScrollPane scrollPane1;
protected JList fileList;
}
and the panel which extends the above. This is the class which handles the addition of filenames to the list :
package org.github.alexwibowo.spider.gui
import javax.swing.*
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
class BarcodeMainPanel extends MainPanel {
private DefaultListModel<String> listModel = new DefaultListModel<String>()
BarcodeMainPanel() {
initModels()
initEventHandling()
}
protected void initModels() {
fileList.model = listModel
}
protected void initEventHandling() {
openFolderButton.addActionListener(new ActionListener() {
#Override
void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setLocation(50, 50);
if (chooser.showOpenDialog(BarcodeSpiderMainFrame.instance()) == JFileChooser.APPROVE_OPTION) {
listModel.clear()
File selectedDirectory = chooser.getSelectedFile()
selectedDirectory.eachFile {
listModel.addElement(it.name)
}
} else {
System.out.println("No Selection ");
}
}
})
}
}
The frame which contains the panel (just for completeness) :
package org.github.alexwibowo.spider.gui
import groovy.transform.Synchronized
import javax.swing.*
import java.awt.*
class BarcodeSpiderMainFrame extends JFrame{
private static BarcodeSpiderMainFrame INSTANCE;
BarcodeSpiderMainFrame(String title) throws HeadlessException {
super(title)
}
#Synchronized
public static BarcodeSpiderMainFrame instance() {
if (INSTANCE == null) {
INSTANCE = new BarcodeSpiderMainFrame("Spider")
INSTANCE.minimumSize = new Dimension(800,600)
INSTANCE.maximumSize = new Dimension(1024,768)
INSTANCE.defaultCloseOperation = EXIT_ON_CLOSE
}
INSTANCE.initializeContent()
INSTANCE.visible = true
INSTANCE
}
private void initializeContent() {
BarcodeMainPanel mainPanel = new BarcodeMainPanel()
this.contentPane.add(mainPanel);
}
}
and finally the launcher (just for completeness) :
package org.github.alexwibowo.spider
import org.github.alexwibowo.spider.gui.BarcodeSpiderMainFrame
import javax.swing.*
#Singleton
class SpiderLauncher {
BarcodeSpiderMainFrame barcodeSpiderMainFrame
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SpiderLauncher.instance.run(args);
}
});
}
void run(String[] args) {
barcodeSpiderMainFrame = BarcodeSpiderMainFrame.instance()
barcodeSpiderMainFrame.show()
}
}
This is what fixes it.
In BarcodeSpiderMainFrame, remove the call to setVisible. So it will look something like:
public static BarcodeSpiderMainFrame instance() {
if (INSTANCE == null) {
INSTANCE = new BarcodeSpiderMainFrame("Spider")
INSTANCE.minimumSize = new Dimension(800,600)
INSTANCE.preferredSize = new Dimension(1024,768)
INSTANCE.maximumSize = new Dimension(1024,768)
INSTANCE.defaultCloseOperation = EXIT_ON_CLOSE
}
INSTANCE.initializeContent()
// INSTANCE.visible = true // remove this line
INSTANCE
}
and in the launcher, call setVisible()
#Singleton
class SpiderLauncher {
BarcodeSpiderMainFrame barcodeSpiderMainFrame
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SpiderLauncher.instance.run(args);
}
});
}
void run(String[] args) {
barcodeSpiderMainFrame = BarcodeSpiderMainFrame.instance()
barcodeSpiderMainFrame.pack()
barcodeSpiderMainFrame.setVisible(true) // add this line
}
}
I have added the call to pack(). But i dont think it really matters. How did the above fix my problem? I do not know. It would be great if someone can explain what actually happened.

JFrame Components not showing up

I have a problem that the JFrame is not showing upmy components.
When i opened the GasStationPanel in WindowBuilder it show well, but the MainFrame is show as a blank windows.
Please, I need you help here.
Thanks!
The JFrame code is:
public class MainFrame extends JFrame {
private GasStationPanel pnlMainGasStation;
public MainFrame() throws SecurityException, IOException {
try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
e.printStackTrace();
}
getContentPane().setLayout(new BorderLayout());
this.pnlMainGasStation = new GasStationPanel("all cars","pumps","coffee");
this.add(pnlMainGasStation, BorderLayout.CENTER);
setLocationRelativeTo(null);
setTitle("GasStation");
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
Utils.closeApplication(MainFrame.this);
}
});
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = new Dimension();
frameSize.setSize(screenSize.width*0.7, screenSize.height*0.9);
setSize(frameSize);
setVisible(true);
}
public GasStationPanel getMainPanel() {
return pnlMainGasStation;
}
}
The GasStationPanel Code:
public class GasStationPanel extends JPanel {
private JSplitPane splinterRight, splinterLeft;
private AllCarsPanel allCarsPanel;
private FuelPumpListPanel fuelPumpsListPanel;
private CoffeeHousePanel coffeeHousePanel;
private List<GasStationController> allListeners;
public AllCarsPanel getAllCarsPanel() {
return allCarsPanel;
}
public FuelPumpListPanel getFuelPumpsListPanel() {
return fuelPumpsListPanel;
}
public CoffeeHousePanel getCoffeeHousePanel() {
return coffeeHousePanel;
}
public GasStationPanel(String allCarsStr, String fuelPumpsListStr,
String coffeeHousePanelStr) throws SecurityException, IOException {
// Init Listeners List
this.allListeners = new ArrayList<GasStationController>();
// Layout and size
setLayout(new BorderLayout());
// Build panels
allCarsPanel = new AllCarsPanel();
fuelPumpsListPanel = new FuelPumpListPanel();
coffeeHousePanel = new CoffeeHousePanel();
// Split the screen to three
splinterRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splinterLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splinterLeft.setLeftComponent(allCarsPanel);
splinterLeft.setRightComponent(fuelPumpsListPanel);
splinterRight.setLeftComponent(splinterLeft);
splinterRight.setRightComponent(coffeeHousePanel);
}
public void registerListener(GasStationController gasStationController) {
this.allListeners.add(gasStationController);
}
In short, you never add any components to your container. For example, in your GasStationPanel code, perhaps you should try invoking add(Component) by passing in your JSplitPanes as an argument. For example:
add(splinterLeft, BorderLayout.CENTER);

History GWT demo - does not work

I have played for a while with History in gwt because i intend to implement it in my current project, so i created a small demo project just to see how it works and do some practice.
So, for some reasons it does not work.
Here is the code - very simple back and forward.
here is the iframe
<iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>
then the entry point
public class EntryPoint implements com.google.gwt.core.client.EntryPoint {
private FirstPanel panel;
public void onModuleLoad() {
ContentPanel panel = ContentPanel.getInstance();
panel.setContent(FirstPanel.getInstance());
RootPanel.get().add(panel);
}
}
and 3 singleton forms, content where form are being loaded and 2 form.
public class ContentPanel extends Composite
{
private static ContentPanel instance;
private static VerticalPanel panel = new VerticalPanel();
private ContentPanel()
{
initWidget(panel);
}
public void setContent(Widget widget)
{
panel.clear();
panel.add(widget);
}
public static ContentPanel getInstance()
{
if(instance == null)
return instance = new ContentPanel();
else
return instance;
}
}
and ..
public class FirstPanel extends Composite implements HistoryListener {
private static FirstPanel instance;
private VerticalPanel panel;
public FirstPanel() {
History.addHistoryListener(this);
panel = new VerticalPanel();
panel.setStyleName("panelstyle");
Button button2 = new Button("Next page");
button2.addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent event)
{
History.newItem("second_page");
}
});
panel.add(button2);
initWidget(panel);
}
public static FirstPanel getInstance()
{
if(instance == null)
return instance = new FirstPanel();
else
return instance;
}
public Widget getWidget() {
return panel;
}
public void onHistoryChanged(String historyToken) {
if(historyToken.equalsIgnoreCase("second_page"))
ContentPanel.getInstance().setContent(SecondPanel.getInstance());
}
}
and the last but not least :))
public class SecondPanel extends Composite implements HistoryListener
{
private static SecondPanel instance;
public SecondPanel()
{
History.addHistoryListener(this);
VerticalPanel verticalPanel = new VerticalPanel();
TextBox firstnameBox = new TextBox();
TextBox lastnameBox = new TextBox();
Button submitButton = new Button("Click");
verticalPanel.add(firstnameBox);
verticalPanel.add(lastnameBox);
verticalPanel.add(submitButton);
submitButton.addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent event)
{
History.newItem("first_panel");
alert("You are in second panel");
}
});
initWidget(verticalPanel);
}
public static SecondPanel getInstance()
{
if(instance == null)
return instance = new SecondPanel();
else
return instance;
}
public void onHistoryChanged(String historyToken)
{
if(historyToken.equalsIgnoreCase("first_panel"))
ContentPanel.getInstance().setContent(FirstPanel.getInstance());
}
}
The problem is that i click the button in FirstPanel and SecandPanel is loaded then press "Back" in the browser does not do anything.In onHistoryChanged method the param historyToken is empty string, should't be a value from the stack (first_page)?
I will be grateful if someone find the problem or explain me where i do mistakes.
Thanks
On first page load you are calling onHistoryChanged(INIT_STATE) by hand. This does not change history. Replace with this:
public FirstPanel() {
History.addHistoryListener(this);
String token = History.getToken();
if (token.length() == 0) {
History.newItem(INIT_STATE);
} else {
History.fireCurrentHistoryState();
}
.. rest of code
Better practice would be to register History listeners History.addHistoryListener(..) only in the top-most panel (EntryPoint or ContentPanel) and switch panels based on history from there.

Launching JFrame from a button

I've got the following button...
public void actionPerformed(ActionEvent arg0) {
Contacts contact = new Contacts();
contact.setVisible(true);
}
Contacts is just a simple JApplet...
public class Contacts extends JApplet {
private JPanel jContentPane = null;
public Contacts() {
super();
}
public void init() {
this.setSize(500, 260);
this.setContentPane(getJContentPane());
}
private JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.add(getJList(), null);
jContentPane.add(getJButton(), null);
jContentPane.add(getJButton1(), null);
}
return jContentPane;
}
}
Why is what I'm doing not working? How would I launch this JFrame?
Like JFrame and JDialog, JApplet is a top-level container. You can't put one inside the other. Instead, do something like this:
class Contacts extends JFrame { ... }
...
Contacts contact = new Contacts();
contact.setVisible(true);
If you have an existing JApplet that you want to display in a JFrame, you can create a hybrid, as shown in the examples examined here.

How would I go about highlighting an item in a JList? [duplicate]

I am trying to change JList rows dynamically. I need change nth row colour, highlight it(n is unknown during compilation). I saw a lot of examples with custom ListCellRenderer, but all were "static".
In other words I have JList with x rows. During runtime my "business logic" detects nth row is important. So I want make its background green, wait one second, and then make it white again. One more thing, don't wan change row selection.
What is the best way to do so?
Simple, set a custom ListCellRenderer to your JList using:
list.setCellRenderer(myListCellrenderer);
Now inside the overridden method getListCellRendererComponent() do something like this:
public Component getListCellRendererComponent(.....) {
Component c = super.getListCellRendererComponent();
c.setBackGround(Color.blue)
return c;
}
The above example assumed that your custom renderer overrid DefaultListCellRenderer
Based on ListDemo sample from SUN.
If you enter some text in the textfield which isn't in the list and you hit highlight it gets added.
If the text is in the list and you hit highlight the entry in the list gets temporarily highlighted blue.
Note the solution here with the match field is just for demo. For more correct implementation consider the other ideas proposed and consider using javax.swing.Timer
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class ListDemo extends JPanel {
private JList list;
private DefaultListModel listModel;
public String match = null;
private static final String hireString = "Highlight";
private JTextField employeeName;
public ListDemo() {
super(new BorderLayout());
listModel = new DefaultListModel();
listModel.addElement("Test1");
listModel.addElement("Test2");
listModel.addElement("Test3");
list = new JList(listModel);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0);
list.setVisibleRowCount(5);
list.setCellRenderer(new MyListCellRenderer());
JScrollPane listScrollPane = new JScrollPane(list);
JButton hireButton = new JButton(hireString);
HireListener hireListener = new HireListener(hireButton);
hireButton.setActionCommand(hireString);
hireButton.addActionListener(hireListener);
hireButton.setEnabled(false);
employeeName = new JTextField(10);
employeeName.addActionListener(hireListener);
employeeName.getDocument().addDocumentListener(hireListener);
listModel.getElementAt(list.getSelectedIndex()).toString();
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane,
BoxLayout.LINE_AXIS));
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(employeeName);
buttonPane.add(hireButton);
buttonPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
add(listScrollPane, BorderLayout.CENTER);
add(buttonPane, BorderLayout.PAGE_END);
}
class MyListCellRenderer extends JLabel implements ListCellRenderer {
public MyListCellRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(JList paramlist, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
if (value.toString().equals(match)) {
setBackground(Color.BLUE);
SwingWorker worker = new SwingWorker() {
#Override
public Object doInBackground() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) { /*Who cares*/ }
return null;
}
#Override
public void done() {
match = null;
list.repaint();
}
};
worker.execute();
} else
setBackground(Color.RED);
return this;
}
}
class HireListener implements ActionListener, DocumentListener {
private boolean alreadyEnabled = false;
private JButton button;
public HireListener(JButton button) {
this.button = button;
}
public void actionPerformed(ActionEvent e) {
String name = employeeName.getText();
if (listModel.contains(name)) {
match = name;
list.repaint();
employeeName.requestFocusInWindow();
employeeName.selectAll();
return;
}
if (name.equals("")) {
Toolkit.getDefaultToolkit().beep();
employeeName.requestFocusInWindow();
employeeName.selectAll();
return;
}
int index = list.getSelectedIndex();
if (index == -1)
index = 0;
else
index++;
listModel.insertElementAt(employeeName.getText(), index);
employeeName.requestFocusInWindow();
employeeName.setText("");
list.setSelectedIndex(index);
list.ensureIndexIsVisible(index);
}
public void insertUpdate(DocumentEvent e) {
enableButton();
}
public void removeUpdate(DocumentEvent e) {
handleEmptyTextField(e);
}
public void changedUpdate(DocumentEvent e) {
if (!handleEmptyTextField(e))
enableButton();
}
private void enableButton() {
if (!alreadyEnabled)
button.setEnabled(true);
}
private boolean handleEmptyTextField(DocumentEvent e) {
if (e.getDocument().getLength() <= 0) {
button.setEnabled(false);
alreadyEnabled = false;
return true;
}
return false;
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("ListDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new ListDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() { createAndShowGUI(); }
});
}
}
Your custom ListCellRenderer, which implements the method getListCellRendererComponent, will have access to both the JList and the value that it is redering. This gives you a couple options for how to determine when to paint the nth row green:
You could subclass JList and have the renderer ask it which color to use for the bg. The JList subclass could trigger a repaint when the business logic determines that it is time for the nth row to be green, and then start an Swing Timer to trigger a repaint returning the bg back to normal
When the business logic determines when you should show the row as green, you also have the option of setting state on the backing object of the row, and test it for that state within getListCellRendererComponent, setting the bg green if the state is correct. Again, you have the option of setting an Swing Timer to revert the state on the backing object.

Categories