How do I go about creating what I describe below?
First, here is the basic look of my GUI:
When I click on Add New Account I want to have the GUI pop up a small window where the user can enter log-in credentials. I would need this information to be passed back into the main GUI, so I am lost as how to approach this.
The same goes for Preferences or Remove Account. How do I go about creating a "GUI Overlay" of sorts. Sorry, I can't figure out the correct terminology for the effect I am looking for.
I wanted to attempt to use JOptionPane's, but after some research this seemed like it was not the route to be taking.
I was also toying with the idea of creating a new JFrame when the action was preformed. How should this be approached?
Start by using dialogs over frames. Dialogs are designed to gather small pieces of information from the user.
I would create a separate component for each operation you want to perform. Within these components I would provide setters and getters to allow you to gain access to the information managed by the component.
From there I would either use a JOptionPane or JDialog to display the component to the user. The reason for using one over the other for me comes down to begin able to control the action buttons (Okay and Cancel for example). For something like the login dialog, I want to restrict the user from begin able to hit the Login button until they've provided enough information to make the attempt.
The basic follow would be something like this...
LoginDialog dialog = new LoginDialog(SwingUtilities.getWindowAncestor(this)); // this is a reference any valid Component
dialog.setModal(true); // I would have already done this internally to the LoginDialog class...
dialog.setVisible(true); // A modal dialog will block at this point until the window is closed
if (dialog.isSuccessfulLogin()) {
login = dialog.getLogin(); // Login is a simple class containing the login information...
}
The LoginDialog might look something like this...
public class LoginDialog extends JDialog {
private LoginPanel loginPane;
public LoginDialog(Window wnd) {
super(wnd);
setModal(true);
loginPane = new LoginPanel();
setLayout(new BorderLayout());
add(loginPane);
// Typically, I create another panel and add the buttons I want to use to it.
// These buttons would call dispose once they've completed there work
}
public Login getLogin() {
return loginPane.getLogin();
}
public boolean isSuccessfulLogin() {
return loginPane.isSuccessfulLogin();
}
}
The dialog is simply acting as proxy/container for the login pane.
This is, of course an overview, you will need to fill in the blanks ;)
Now, if you don't want to go to the trouble of creating your own dialog, you can take advantage of the JOptionPane instead.
LoginPanel loginPane = new LoginPanel();
int option = JOptionPane.showOptionDialog(
this, // A reference to the parent component
loginPane,
"Login", // Title
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null, // You can supply your own icon it if you want
new Object[]{"Login", "Cancel"}, // The available options to the user
"Login" // The "initial" option
);
if (option == 0) {
// Attempt login...
}
Related
Well, I actually feel stupid for even asking this question but: Is it possible for an ActionListener to loop back on it self? The situation is as follows (kind shorthandish because it is a lot of in itself sound code that does nothing to the problem)
JMenuItem Menu=new JMenuItem();
Menu.addActionListener(e -> {
JDialog Dialog=new JDialog();
JTextField Name= new JTextField("",30);
JFormattedTextField ID =new JFormattedTextField(NumberFormat.getIntegerInstance());
ID.setColumns(8);
JButton Enter=new JButton();
\\GUI building stuff
Enter.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
Integer ImportID=((Number) ID.getValue()).intValue();
String ImportName= Name.getText();
System.out.println("Eingaben\n"+ImportID);
System.out.println(ImportName);
//loads of different stuff
Dialog.dispose();
System.out.println(ImportID);
System.out.println(ImportName);
//ID.setValue(null);
//Name.setText(null);
//ImportID=null;
//ImportID=null;
System.out.println("Fertig!");
}
});
});
Now this menu leads to a dialog intended as an import dialog. What happens now is that the first time any user input data is used this data is propagated correctly. But if the user attempts make a input a second time the first and the second values are handed through - even with the disposing of the Dialog the data of the first go through shouldn't even be accessible, right?
I tried replacing the inner ActionListener with an e.getSource, which didn't work. Setting the variables or the Field to null doesn't help either.
I am aware that placing an ActionListener within an ActionListener is propably bad form.
Edit: I should explain how this works: The MenuItem (which sits inside the menubar of a proper GUI) is selected and calls forth a Dialog where the user enters two pieces of data and selects some files. Selected files are copied into a new directory and the entered data is processed into two text files. After that happened the Dialog is set to invisible and some different and to the data unrelated processing occurs. This processign being finished things are supposed to be wrapped up so that the dialog can be called upon again. If however I close the application this error does not occur.
I have started implementing JCEF in a project of mine, and I am initializing the embedded browser in a JInternalFrame inside of a JFrame, alongside a series of form fields on a JPanel next to the JInternalFrame. The browser component doesn't fully initialize until the JFrame actually becomes visible, and I'm finding that my JTextFields are uneditable unless the JFrame loses and regains focus.
Any idea of what could be happening and how to fix it? This only happens when using a JInternalFrame with the JCEF component...
It also happens every time I call loadURL to load a new page in the browser: the JTextFields become uneditable again, until I lose/gain focus in the JFrame.
UPDATE:
I have found a hack which allows the JTextFields to become editable again, but I wouldn't call it a solution because it is not very elegant. I added a load handler to the CefClient instance ( client.addLoadHandler(new CefLoadHandlerAdapter()) ) with an #Ovveride on the onLoadingStateChange method, which in turn gives access to the current browser component. From there I can detect when loading in the browser is complete, and use SwingUtilities to get the Window that the browser component is in. Then I setVisible(false) and setVisible(true) on that Window. I say it's not a solution because every time the browser is done loading the Window disappears and reappears. Even though the JTextFields are editable again, it is quite ugly to see the window flashing. I've tried all kinds of revalidate() and repaint() methods to no avail, unless I didn't call them right...
client.addLoadHandler(new CefLoadHandlerAdapter() {
#Override
public void onLoadingStateChange(CefBrowser browser, boolean isLoading,
boolean canGoBack, boolean canGoForward) {
if (!isLoading) {
//browser_ready = true;
System.out.println("Browser has finished loading!");
SwingUtilities.windowForComponent( browser.getUIComponent() ).setVisible(false);
SwingUtilities.windowForComponent( browser.getUIComponent() ).setVisible(true);
}
}
});
If anyone can suggest a better solution, please do!
I figured out the problem by studying the sample JCEF application a little better. I need to implement a FocusHandler in order to release the embedded browser's hold on keyboard input:
private boolean browserFocus_ = true;
---
jTextField1.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
if (!browserFocus_) return;
browserFocus_ = false;
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
jTextField1.requestFocus();
}
});
I am looking to figure out how to set the text of a label on an external Application Window.
What I have:
I have two windows so far. The first one is the main application window that will appear when the user starts the program. The second window is another separate window that I have created specifically to display a custom error window.
The problem: I seem to be unable to call the label that I have created on the error window and set the text to something custom. Why? I want to be able to reuse this window many times! This window is aimed for things like error handling when there is invalid input or if the application cannot read/save to a file.
I was going to post screen shots but you need 10 rep for that. It would have explained everything better.
Here is the code for the label on the Error_dialog window:
Label Error_label = new Label(container, SWT.NONE);
Error_label.setBounds(10, 10, 348, 13);
Error_label.setText("Label I actively want to change!");
Here is the condition I would like to fire off when it is met:
if(AvailableSpaces == 10){
//Set the label text HERE and then open the window!
showError.open();
}
I have included this at the top of the class as well:
Error_dialog showError = new Error_dialog();
Just save the label as a field in your dialog class and add a 'setter' method. Something like:
public class ErrorDialog extends Dialog
{
private Label errorLabel;
... other code
public void setText(String text)
{
if (errorLabel != null && !errorLabel.isDisposed()) {
errorLabel.setText(text);
}
}
You will need to use your dialog like this:
ErrorDialog dialog = new ErrorDialog(shell);
dialog.create(); // Creates the controls
dialog.setText("Error message");
dialog.open();
Note: you should stick to the rules for Java variable names - they always start with lower case.
Further learn to use Layouts. Using setBounds will cause problems if the user is using different fonts.
Before I start, Hi. This is is my first question here. I am not good with Java so have been trying and improve that and here it goes.
I am trying to create an email client and server application using sockets in Java. However I have been running into a problem. I have created a jFrame which is basically the Welcome window. The code is too huge to post so I'll post the relevant portions. There is a preferences jDialog. When the OK button on the dialog, an action handler comes in to play. The code:
private void okActionPerformed(java.awt.event.ActionEvent evt) {
Welcome wel = new Welcome();
wel.setStatusBar("Pressed OK");
dispose();
}
Obviously, the setStatusBar() sets the text of the statusLabel. The code for setStatusBar():
public void setStatusBar(String s)
{
statusLabel.setText(s);
}
Also, the preferences dialog is opened through menu item with this code:
private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {
settings pref=new settings(null,true);
pref.show();
}
The problem is if I set the status label from any other class, for instance settings class, it does not reflect but if I do so from the Welcome class ( the class where the statusLabel is present), it works fine. This problem is not only limited to this setStatus() but virtually pops up whenever I try to use a method of a different class.
If you guys need more of the code, I could post it. I would be grateful if could help a Java beginner out.
Thanks.
private void okActionPerformed(java.awt.event.ActionEvent evt) {
Welcome wel = new Welcome();
wel.setStatusBar("Pressed OK");
dispose();
}
You're creating a new (hence the keyword new) object of type Welcome. This new object is different from the already existing object of type Welcome, that you have created earlier. It thus has its own label, and you're setting the text of this different label, which is not displayed anywhere in the screen.
Java objects work like regular object. Let's say you would like a cool logo on one of your blue t-shirts. You go to a T-shirt vendor and ask him to print a cool logo. The vendor doesn't have your blue t-shirt. If the vendor gets another red t-shirt from his shop and prints the logo on this red t-shirt, your blue t-shirt will still have no logo at all.
For the vendor to be able to print a logo on your blue t-shirt, you need to give him this blue t-shirt. Same in Java: you need to pass the existing Welcome object to the preferences dialog, and the actionPerformed method must set the label on this Welcome object. Not on a new Welcome object.
Greetings to Swing Pros, here's a good (I hope) question for you.
The below are the task requirements and possible solutions I see. I would like someone having had such a hardcore experience to share some thoughts about this.
This does not require coding or anything like that, I just need general advice as to which approach is more reliable regarding the fact I need to work with private symbols which reside in sun.swing and/or javax.swing.plaf packages.
The task is to modify/alter JFileChooser behaviour (just a little bit, actually).
when the user presses enter in the file name JTextField, and the field contains a path to a dir, don't "select" the dir, but switch to it instead. Yes, the dialog is configured to accept directories, but we need to accept only clicks on the "Open" button, and (possibly) double-clicks in the file listing table.
prevent user from selecting a dir/file with more than 1GB data via hitting enter in the file name text field
Here're couple of general solution options:
a. listen on the property-based changes that JFileChooser provides (which AFAICS are triggered after-the-fact and won't provide the degree of control we need here).
b. tinker with the javax.swing.plaf.basic.BasicFileChooserUI (via refrection, breaking the private-level encapsulation) and alter the reference to
private Action approveSelectionAction = new ApproveSelectionAction();
so that our custom action does the extra checks for 1 and 2. This approach links with plaf package and may fail in case this action is somehow overridden in some class below this UI class.
c. traverse the JFileChooser component hierarchy, find the JTextField (which apparently should occur only once in the component tree), decorate all the action listeners hanging on that JTextField with our custom checks. My debugging session shows that this JTextField is some anonymous subclass of JTextField living in the sun.swing.FilePane.
This approach seems to be more OO-friendly, but there's a chance that for some OS this text field is absent, or some other JTextField is also present in the hierarchy.
Well, it seems that public JFileChooser API would not suffice to achieve that behaviour, while the other two options are either deep magic or unportable (long-term), or even both.
So, the question is: which approach would you choose and why?
Regarding option2, you don't need to use reflection to customize the accept Action. You can just override the approveSelection() method. Something like:
JFileChooser chooser = new JFileChooser( new File(".") )
{
public void approveSelection()
{
if (getSelectedFile().exists())
{
System.out.println("duplicate");
return;
}
else
super.approveSelection();
}
};
I recently encountered the same requirement, i.e., pressing Enter in the JTextField of a JFileChooser should cause the displayed dialog to traverse a directory instead of returning from the dialog. Only clicking on the Open button should cause the final selection.
The solution was fairly simple (at least for my application) and has two components to it (Pardon the messed up formatting. I'm new to this forum and I'm not sure why the code is not displaying correctly).
1 - Register an AWTListener to keep track of the last event type generated by the user
class MyChooser extends JFileChooser implements java.awt.AWTEventListener {
...
MyChooser(){
Toolkit.getDefaultToolkit().addAWTEventListener(this,
AWTEvent.MOUSE_EVENT_MASK + AWTEvent.KEY_EVENT_MASK);
...
}
int lastEventId;
public void eventDispatched(AWTEvent e) {
lastEventId=e.getID();
}
}
2 - Override the approveSelection() method of JFileChooser and check whether the approval request is a result of a mouse event (likely caused by the user clicking on the Open button) or a key event caused by the user pressing Enter. The 'lastEventId' variable provides access to this information. My own approveSelection then looks as follows:
public void approveSelection() {
File f=getSelectedFile();
if (f.exists() && isTraversable(f) && lastEventId ==
KeyEvent.KEY_PRESSED) {
setCurrentDirectory(f);
return;
}
super.approveSelection(); }