JCheckBox State Remain Consistent Among Classes - java

I have a help pane which appears at the start of a program, but can be turned off. If the user wants it to return, there is an option in the menu bar to reactivate it. However, when they choose to show it from the help menu, it automatically rechecks the "do not show again" box. How do I keep the box in the same state the user originally had it, but still open the help pane?
Gui:
public class Gui {
private Game game;
private JFrame frame;
private MenuBar menuBar;
private HelpDialog helpMenu;
private boolean showHelp;
public Gui(Game game) {
this.game = game;
this.showHelp = true;
this.createAndShowGUI();
}
public boolean shouldShowHelpDialog() {
return this.showHelp;
}
public void displayHelp() {
this.helpMenu.showHelpDialog();
}
MenuBar:
public class MenuBar {
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem menuItem;
private JFrame frame;
private Gui gui;
private Game game;
public MenuBar(JFrame frame, Gui gui, Game game) {
this.menuBar = new JMenuBar();
this.frame = frame;
this.gui = gui;
this.game = game;
}
public void buildMenuBar() {
this.buildFileMenu();
this.buildSettingsMenu();
this.buildHelpMenu();
this.frame.setJMenuBar(this.menuBar);
}
private void buildHelpMenu() {
this.menu = new JMenu("Information");
this.menu.setMnemonic(KeyEvent.VK_I);
this.menu.getAccessibleContext().setAccessibleDescription("Help menu");
JMenuItem menuHelp = new JMenuItem("Help", KeyEvent.VK_H);
menuHelp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
MenuBar.this.gui.displayHelp();
}
});
this.menu.add(menuHelp);
this.menuBar.add(this.menu);
}
HelpDialog:
public class HelpDialog {
private boolean shouldShowHelpDialog;
private JFrame theFrame;
public HelpDialog(boolean helpDialog, JFrame frame) {
this.shouldShowHelpDialog = helpDialog;
this.theFrame = frame;
}
public boolean showHelpDialog() {
if (!this.shouldShowHelpDialog) {
return false;
}
JCheckBox shouldShowCheckBox = new JCheckBox("Do not show this message again", this.shouldShowHelpDialog);
Object[] msgContent = { this.buildHelpPane(), shouldShowCheckBox };
JOptionPane.showMessageDialog(this.theFrame, msgContent, "Help", JOptionPane.INFORMATION_MESSAGE);
return shouldShowCheckBox.isSelected();
}
private Object buildHelpPane() {
String helpMessage = "Game rules: This is how you play.";
JTextArea helpTextArea = new JTextArea(helpMessage);
helpTextArea.setRows(6);
helpTextArea.setColumns(40);
helpTextArea.setLineWrap(true);
helpTextArea.setWrapStyleWord(true);
helpTextArea.setEditable(false);
helpTextArea.setOpaque(false);
JScrollPane helpPane = new JScrollPane(helpTextArea);
return helpPane;
}
}
EDIT:
Updated HelpDialog class:
public class HelpDialog {
private boolean shouldShowHelpDialog;
private JFrame theFrame;
private JCheckBox shouldShowCheckBox;
public HelpDialog(boolean helpDialog, JFrame frame) {
this.shouldShowHelpDialog = helpDialog;
this.theFrame = frame;
this.shouldShowCheckBox = new JCheckBox("Do not show this message again", this.shouldShowHelpDialog);
}
public boolean showHelpDialog() {
if (!this.shouldShowHelpDialog) {
return false;
}
Object[] msgContent = { this.buildHelpPane(), shouldShowCheckBox };
JOptionPane.showMessageDialog(this.theFrame, msgContent, "Help", JOptionPane.INFORMATION_MESSAGE);
return shouldShowCheckBox.isSelected();
}
The checkbox remains unmarked now when displaying the help menu through the menu bar. However, now when a new game is created, it will show the help dialog even if the box is unchecked.
Full answer includes this change to the method in the GUI:
public void displayHelp() {
this.showHelp = this.helpMenu.showHelpDialog();
}

Your showHelpDialog() method creates a new checkbox each time it is called. You should create the dialog once in the constructor, and showHelpDialog() should just display it.

You can add a parameter to showHelpDialog which overrides your request
public boolean showHelpDialog(boolean override) {
if(!override){
if (!this.shouldShowHelpDialog) {
return false;
}
}
JCheckBox shouldShowCheckBox = new JCheckBox("Do not show this message again", this.shouldShowHelpDialog);
Object[] msgContent = { this.buildHelpPane(), shouldShowCheckBox };
JOptionPane.showMessageDialog(this.theFrame, msgContent, "Help", JOptionPane.INFORMATION_MESSAGE);
return shouldShowCheckBox.isSelected();
}
and call
showHelpDialog(true);
when clicked from menu.

Related

Update JMenu in Swing via revalidate() and repaint() not working

In the process of logging in, if the administrator is being logged in I want to enable JMenuItem called Admin. When program starts, its visibility is set to false. So when a user clicks Log In I run JMenu again and trying to recreate it just with Admin now set on true. Here's the code of my initialize method that's being run if it detects the user is an admin. The method is inside the JMenuBar class that the application uses.
public void initialize() {
file = new JMenu("File");
file.setName("File Menu");
file.addMouseListener(this);
help = new JMenu("Help");
help.setName("Help Menu");
help.addMouseListener(this);
login = new JMenu("Login");
login.setName("Login Menu");
login.addMouseListener(this);
language = new JMenu("Language");
language.setName("Language Menu");
language.addMouseListener(this);
admin = new JMenu("Admin");
admin.setName("Admin Menu");
if(LoginDialog.AdminLoggedIn) {
admin.setEnabled(true);
} else
admin.setEnabled(false);
admin.addMouseListener(this);
add(file);
add(login);
add(help);
add(language);
add(admin);
this.revalidate();
this.repaint();
}
Thanks.
I would suggest not re-creating your JMenu but rather modifying it, depending on the Administrator state of your program. You could give the program a Privileges enum, one with REGULAR and ADMINISTRATOR (and possibly other) fields, something like:
public enum Privileges {
REGULAR("Regular"), ADMINISTRATOR("Administrator");
private String text;
private Privileges(String text) {
this.text = text;
}
#Override
public String toString() {
return text;
}
}
And then change the state of your JMenu depending on the program's Privileges state. Also side note: don't use a MouseListener on your menus since these do not respect the enabled/disabled state of your menus / menuitems / buttons. For example, here is my small MVCE example, one that uses a Model-View-Controller structure (of sorts):
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
#SuppressWarnings("serial")
public class MenuChanger extends JPanel {
private CreateMenu createMenu = new CreateMenu();
private MenuChngModel model = new MenuChngModel();
private ButtonGroup buttonGroup = new ButtonGroup();
public MenuChanger() {
setPreferredSize(new Dimension(400, 300));
model.addPropertyChangeListener(MenuChngModel.PRIVILEGES, new ModelListener());
JPanel privilegesPanel = new JPanel();
privilegesPanel.setLayout(new GridLayout(0, 1, 5, 5));
privilegesPanel.setBorder(BorderFactory.createTitledBorder("Privileges"));
for (final Privileges privileges : Privileges.values()) {
JRadioButton rBtn = new JRadioButton(privileges.toString());
if (privileges == Privileges.REGULAR) {
rBtn.setSelected(true);
}
rBtn.addActionListener(e -> {
createMenu.setPrivileges(privileges);
});
buttonGroup.add(rBtn);
privilegesPanel.add(rBtn);
}
add(privilegesPanel);
}
public CreateMenu getCreateMenu() {
return createMenu;
}
private class ModelListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
Privileges privileges = (Privileges) evt.getNewValue();
createMenu.setPrivileges(privileges);
}
}
private static void createAndShowGui() {
MenuChanger mainPanel = new MenuChanger();
JFrame frame = new JFrame("MenuChanger");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setJMenuBar(mainPanel.getCreateMenu().getMenubar());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MenuChngModel {
public static final String PRIVILEGES = "privileges";
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
private Privileges privileges = Privileges.REGULAR;
public Privileges getPrivileges() {
return privileges;
}
public void setPrivileges(Privileges privileges) {
Privileges oldValue = this.privileges;
Privileges newValue = privileges;
this.privileges = privileges;
pcSupport.firePropertyChange(PRIVILEGES, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(name, listener);
}
}
enum Privileges {
REGULAR("Regular"), ADMINISTRATOR("Administrator");
private String text;
private Privileges(String text) {
this.text = text;
}
#Override
public String toString() {
return text;
}
}
class CreateMenu {
private JMenuBar menubar = new JMenuBar();
private JMenu fileMenu = new JMenu("File");
private JMenu adminMenu = new JMenu("Administrator");
private JMenuItem fileMenuItem = new JMenuItem("File Menu Item");
private JMenuItem adminFileMenuItem = new JMenuItem("Admin File Menu Item");
public CreateMenu() {
fileMenu.setMnemonic(KeyEvent.VK_F);
adminMenu.setMnemonic(KeyEvent.VK_A);
fileMenu.add(fileMenuItem);
fileMenu.add(adminFileMenuItem);
adminMenu.add(new JMenuItem("Foo 1"));
adminMenu.add(new JMenuItem("Foo 2"));
adminFileMenuItem.setEnabled(false);
adminMenu.setEnabled(false);
menubar.add(fileMenu);
menubar.add(adminMenu);
}
public void setPrivileges(Privileges privileges) {
switch (privileges) {
case REGULAR:
adminMenu.setEnabled(false);
adminFileMenuItem.setEnabled(false);
break;
case ADMINISTRATOR:
adminMenu.setEnabled(true);
adminFileMenuItem.setEnabled(true);
break;
default:
break;
}
}
public JMenuBar getMenubar() {
return menubar;
}
}

JAVA cardLayout. how to call a card from different classes

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);

Hide Java application to System Tray

I want to hide my Java application from the taskbar and for it to be visible only at the system tray. Here is a picture in case this is unclear.
I tried to implement it like this and the icon did appear in the system tray but it is still showing the application on the taskbar.
Here is part of the Frame class
public class Widget extends JFrame {
private static final long serialVersionUID = -197136854089859547L;
private JPanel mainPanel;
private WidgetProperties properties;
private Makedir mkdir;
private ArrayList<Item> items;
private Image icon;
private TrayIcon trayIcon;
private SystemTray tray;
public Widget() {
super("");
this.setTray();
this.setUndecorated(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void setTray() {
tray = SystemTray.getSystemTray();
PopupMenu menu = new PopupMenu();
MenuItem show = new MenuItem("Show");
MenuItem exit = new MenuItem("Exit");
show.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
setState(Frame.NORMAL);
}
});
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
close();
}
});
menu.add(show);
menu.addSeparator();
menu.add(exit);
trayIcon = new TrayIcon(icon, "EasyStart", menu);
trayIcon.setImageAutoSize(true);
try
{
tray.add(trayIcon);
} catch (AWTException e) {
e.printStackTrace();
}
}
public void setup() {
this.resize();
this.setVisible(true);
}
public void resize() {
this.setResizable(true);
this.setShape(properties.getShape());
this.setSize(properties.getSize());
this.setResizable(false);
}
public void close() {
System.exit(0);
}
}
I just need to find how to hide the application from the taskbar.
do this setVisible(false) then there will be nothing in the taskbar

Java code needs to restrict the user input

I got a serious problem on my code.
I got a swing JDBC code which I need to fill a table of names, addresses and an ID for the person, different than the table's ID. I created a swing input code for it, however, I wish it NOT to include the ID number's possibility - therefore, to make the swing have nothing else but the name and address being able to be set by the used, and not to show the ID at all.
Is there a possibility for it?
The creation of new partner, which has the name, address and the IdentityNumber strings, all private and their getters and setters public.
{
protected final String FRAME_TITLE = "Vehicle Repository";
private DatabaseHandler dbHandler;
private JTabbedPane tabbedPane;
private JTable partnerTable;
private JpaControlledTableModel<Partner> partnerTableModel;
#Override
public void onCreate() {
setDefaults(FRAME_TITLE);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
dbHandler = new DatabaseHandler();
dbHandler.open();
tabbedPane = new JTabbedPane();
partnerTableModel = new AsyncFullQueryingTableModel<>(dbHandler.getPartnerJpaController(), dbHandler.getEntityClassesToControllersMap());
parterTable = new JTable(partnerTableModel);
tabbedPane.addTab("Partners", new JScrollPane(parterTable));
getContentPane().add(tabbedPane, BorderLayout.CENTER);
}
#Override
public JMenuBar createJMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Data");
menuBar.add(menu);
JMenuItem menuItem;
menuItem = new JMenuItem(newPartnerAction);
menu.add(menuItem);
return menuBar;
}
private Action newPartnerAction = new AbstractAction("New parnter") {
#Override
public void actionPerformed(ActionEvent e) {
Partner partner = new Partner();
EntityEditorDialog<Partner> editorDialog = EntityEditorDialogFactory.createEditorDialog(partner, dbHandler.getPartnerJpaController());
editorDialog.setVisible(true);
if (partner.getId() != null) {
partnerTableModel.refresh();
}
}
};
private String getString(String message) {
return JOptionPane.showInputDialog(rootPane, message, "Data input", JOptionPane.QUESTION_MESSAGE);
}
private Partner getPartner(String message) {
Object[] partners = dbHandler.getPartnerJpaController().findEntities().toArray();
if (partners.length == 0) {
return null;
} else {
return (Partner) JOptionPane.showInputDialog(rootPane, message, "Data input", JOptionPane.QUESTION_MESSAGE, null, partners, partners[0]);
}
}
#Override
public void dispose() {
dbHandler.close();
super.dispose();
}
}
};
and not to show the ID at all
You can remove a column from display in the JTable:
table.removeColumn( table.getColumn(...) );

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.

Categories