I have a menu with items that open internal frames, but every time I need to click twice in the frame. One time to give focus to the Int.frame and the second time to actually do something (give focus to a textfield).
So, here is my question: It's possible to automatic give focus to the Int.Frame?
Code of my main screen:
public final class principal extends javax.swing.JFrame {
viewCity city = new viewCity();
public principal() {
initComponents();
myListeners();
setLocationRelativeTo(null);
}
public void myListeners() {
menuCity.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
menuCityClicked(e);
}
});
}
public void central(JInternalFrame window1) {
int lDesk = panelPrincipal.getWidth();
int aDesk = panelPrincipal.getHeight();
int lIFrame = window1.getWidth();
int aIFrame = window1.getHeight();
window1.setLocation(lDesk / 2 - lIFrame / 2, aDesk / 2 - aIFrame / 2);
}
private void menuCityClicked(MouseEvent e) {
if (!city.isVisible()) {
panelPrincipal.add(city);
central(city);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
city.setVisible(true);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
}
}}
No matter what, the menu will always keep the focus. For example, click in your browser's menu, and you will keep the focus, by moving the cursor you will open other menus without need to click.
By putting the properties "selection model" to null works, but give me nullpointerexception.
Ok, the problem is with the jMenu, but with jMenuItem Works fine, so... I'm using
Related
I am trying to make a password checker, and I am trying to have an icon set as X until the user meets the condition of the password being at least 8 characters long. I am trying to set up a while loop for while the program is running, which will in turn run another while loop which will update the icon. I am doing this because a want it to always be checking to see if the condition is met and not need the user to click a button for example. I have placed the code inside the initComponents of the public form PasswordCheckerUI, but when I hit run on the program, it says running but my GUI doesn't pop up. How would I change the code to make this work(if needed) or where would I have to move it to? I have tried making a public static void with the code and calling it within the initCompnents, but it yielded the same results. Lastly, I tried to call the method within the main method, but the variables aren't static so that did not work either
public class PasswordCheckerUI extends javax.swing.JFrame {
public PasswordCheckerUI() {
initComponents();
while (Thread.currentThread().isAlive()) {
while (txtPassword.getText().length() < 8) {
lblMinCharIcon.setIcon(X);
if (txtPassword.getText().length() >= 8) {
lblMinCharIcon.setIcon(Check);
}
}
}
}
}
Events in Swing don't just happen when the user clicks on a button - they happen all the time (when moving the mouse, when clicking, when editing text, when ...) and they are therefore the best way to solve your problem.
You can for example listen the document change events on the txtPassword and change the icon depending on the new length of the password:
public class PasswordCheckerUI {
private JTextField txtPassword;
private JLabel lblMinCharIcon;
public PasswordCheckerUI() {
txtPassword = new JTextField(40);
txtPassword.getDocument().addDocumentListener(
new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
checkPasswordLen(txtPassword);
}
#Override
public void removeUpdate(DocumentEvent e) {
checkPasswordLen(txtPassword);
}
#Override
public void changedUpdate(DocumentEvent e) {
checkPasswordLen(txtPassword);
}
}
);
}
private void checkPasswordLen(JTextField tf) {
if (tf.getText().length() < 8) {
lblMinCharIcon.setIcon(x);
} else {
lblMinCharIcon.setIcon(check);
}
}
}
Whenever, I type something in CodeArea and press CTRL + Z and then begin typing again, the cursor gets reset to the start of the text.
I looked into this issue https://github.com/FXMisc/RichTextFX/issues/761 and seems like this bug is fixed. However, I was able to replicate the bug in latest version (0.9.1).
Following code will replicate the behavior:
public class GuiTest extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
StyleClassedTextArea codeArea = new StyleClassedTextArea();
codeArea.replaceText("Text");
VirtualizedScrollPane<StyleClassedTextArea> scrollPane = new VirtualizedScrollPane<>(codeArea);
final Scene scene = new Scene(scrollPane, 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Am I missing something? If the bug exists any idea how to solve it?
After a brief debugging I found that RichTextFx is doing some weird behavior when selecting the new range (it is from this range you start typing the text, cursor position does not matter). When selecting the new range, the current range is set to 0,0 and then only moved to the cursor position. However, after performing the undo, the new range is selected to 0,0 and never to the current cursor position. It is because of that when we press undo, though the cursor is highlighted in another position, the text starts getting typed from the 0,0.
I was able to somewhat solve this using reflection. You need to extend the StyleClassedTextArea, override the undo() method, perform undo, and then set the position where you need your range in. You could set the range to the current cursor position but the cursor is not always in the correct position especially when the cursor needs to move to another style in another paragraph. I got the correct position range inside the ChangeQueue in the undoManager.
You need to make sure that you are casting properly so, do some debugging before casting.
#Override
public void undo() {
if (isUndoAvailable()) {
super.undo();
UndoManager undoManager = getUndoManager();
try {
Field queueField = UndoManagerImpl.class.getDeclaredField("queue");
queueField.setAccessible(true);
UnlimitedChangeQueue queue = (UnlimitedChangeQueue) queueField
.get(undoManager);
int newRange = ((PlainTextChange) ((List) queue.peekNext()).get(0))
.getRemovalEnd();
selectRange(newRange, newRange);
} catch (NoSuchFieldException | IllegalAccessException e) {
// Handle exception
}
}
}
#Override
public void redo() {
if (isRedoAvailable()) {
super.redo();
UndoManager undoManager = getUndoManager();
try {
Field queueField = UndoManagerImpl.class.getDeclaredField("queue");
queueField.setAccessible(true);
UnlimitedChangeQueue queue = (UnlimitedChangeQueue) queueField
.get(undoManager);
int newRange = ((PlainTextChange) ((List) queue.peekPrev()).get(0))
.getInsertionEnd();
selectRange(newRange, newRange);
} catch (NoSuchFieldException | IllegalAccessException e) {
// Handle
}
}
}
I created a SWT dialog with this implementation:
public class FindDialog extends Dialog {
private DialogResult result;
private Display display;
private Shell shell;
private Button okayButton;
/*...*/
public FindDialog(Shell parent) {
this(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
}
public FindDialog(Shell parent, int style) {
super(parent, style);
display = getParent().getDisplay();
initUI();
}
public DialogResult open() {
result = DialogResult.Cancel;
shell.open();
while (shell.isVisible()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
return result;
}
private void initUI() {
shell = new Shell(getParent(), getStyle());
shell.addListener(SWT.Close, new ShellClosingHandler());
okayButton = new Button(shell, SWT.PUSH);
okayButton.addListener(SWT.Selection, new ButtonClickedHandler());
/*...*/
}
private class ButtonClickedHandler implements Listener {
public void handleEvent(Event e) {
Button button = (Button)e.widget;
if (button == okayButton) {
result = DialogResult.OK;
shell.close();
}
}
}
private class ShellClosingHandler implements Listener {
public void handleEvent(Event e) {
if (result == DialogResult.OK) {
e.doit = validate();
}
}
private boolean validate() {
/*...*/
}
}
}
There are some more text fields, buttons and checkboxes but I think that it's not important for my question.
The dialog window popups correctly and I can make my changes on the GUI without any problems.
At last I click the ok button and then the following happens:
The SWT.Close event is firing, my validation method is called and depending on the result the dialog is closed or not. That's ok so far.
But shell.close() not only closes the dialog, it also disposes the shell. And exactly here is the problem because
I don't want to rebuild the dialog GUI everytime the open method is called. I create all my dialogs at program startup and then only want to open and close it if needed.
I need some values of the text fields or states of checkboxes after closing the dialog at different positions in the main program. So it seems a good idea to hold a reference of the dialog object and implement some getters to pull out the data. But if the shell is disposed I have no chance to get the information.
If the shell is disposed then I will loose the "state" of the dialog so I have to refill it next time I display the dialog.
So my question: Is there a possibility to prevent the shell from disposing?
Or is there another concept that I overlooked so I don't have to restructure my complete dialog set?
if (button == okayButton) {
result = DialogResult.OK;
shell.setVisible(false);
}
You can use setVisible(false) instead of close
So it will get hide and wont get dispose.
You can get the values of the text box after hide
No need to rebuild again
The past values in the textbox will be there after hide.
Not sure how well I will explain this; I'm quite new to programming...
So I'm trying to make a desktop application that draws musical notes of a given type on some sheet music when the user selects the button corresponding to that type of note. Currently, if the user selects the "Whole Note" button, the user can then start clicking on the screen and the note will be drawn where the click occurred. It will also make a "ding" sound and write some info about that note to a text file.
That's all well and good, but unfortunately when the user selects a new button, say the "Quarter Note" button, for each mouse click there will be two notes drawn (one whole, one quarter), two dings, and two packets of info written to the file. I have no idea how to make this work! Currently, I'm trying to use threads, such that each button creates a new thread and the thread currently in use is interrupted when a new button is pressed, but that doesn't resolve the issue.
Initially, an empty linked list of threads ("NoteThreads") is constructed. Also, a private class known as SheetMusicPane (given the variable name "smp") is constructed in order to draw the sheet music. The buttons are added in the main constructor (public CompositionStudio), whereas the method containing the mouse listener (see what follows) is contained in the SheetMusicPane private class. Not sure whether that is part of the problem.
I have a button action listener:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!threads.isEmpty()) {
NoteThread oldThread = threads.remove();
oldThread.interrupt();
}
NoteThread newThread = new NoteThread(e.getActionCommand());
threads.add(newThread);
newThread.run();
}
});
that produces a thread:
private class NoteThread extends Thread {
private String note;
public NoteThread(String note) {
this.note = note;
}
public void run() {
smp.getShape(smp.getGraphics(), note);
}
}
that when, on running, calls this method with graphics and a mouse listener:
public void getShape(final Graphics g, final String note) {
this.addMouseListener(new MouseListener() {
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
Point p = MouseInfo.getPointerInfo().getLocation();
addShape(g, p.x, p.y, note);
int pitch = 12;
piano.playNote(pitch);
advance(1.0, piano);
try { addToFile(pitch, note);}
catch(FileNotFoundException fnfe) {}
catch(IOException ioe) {}
}
});
}
The above method is responsible for drawing the note ("addShape()"), making the ding sound, and writing to the file.
Thanks in advance for any help you can give!
what you're trying to do does not require multithreading. This is the approach that I'd take:
set up a set of toggle buttons or radio buttons to select the note to paint. this way, only one note will be selected at a time. add action listeners to those that store in an adequately scoped variable what note is selected, or infer that every time a note should be drawn. this way, you don't even add action listeners to the buttons. in any case, don't spawn new threads.
in your mouse listener, find out what note to draw, and do that - only one note.
if you can, stay away from multithreading, especially as a beginner. also, I think you confuse adding and running listeners here. each call to getShape() adds a new listener, meaning they accumulate over time, which might be the cause of your problems.
PS: welcome to stackoverflow! your question contained the important information and I could infer that you tried solving the problem yourself. It's pleasant to answer such questions!
One solution would be to simply fetch all the listeners (which should be 1) and remove them before adding the new listener:
public void getShape(final Graphics g, final String note) {
MouseListener[] listeners = this.getMouseListeners();
for (MouseListener ml : listeners) {
this.removeMouseListener(ml);
}
this.addMouseListener(new MouseListener()...);
}
An alternative, since you have a finite number of buttons, would be to create a finite set of listeners, eg:
private MouseListener wholeNote = new MouseListener()...;
private MouseListener quarterNote = new MouseListener()...;
Create a reference to the "current" listener (private MouseListener current;), and have a means of deciding which listener to use whenever getShape is called (a series of if conditions on the note String would work, although I would prefer some refactoring to use an enum personally). Then you could do something along the lines of:
private MouseListener wholeNote = new MouseListener()...;
private MouseListener quarterNote = new MouseListener()...;
private MouseListener current;
...
public void getShape(final Graphics g, final String note) {
if (current != null) {
this.removeMouseListener(current);
}
if (...) { // note is Whole Note
current = wholeNote;
} else if (...) { // note is Quarter Note
current = quarterNote;
} // etc.
this.addMouseListener(current);
}
Another alternative would be to change your listener so that you only ever need the one, but clicking a button changes a variable which the listener has access to. For example:
// In the listener
public void mouseClicked(MouseEvent e) {
Point p = MouseInfo.getPointerInfo().getLocation();
addShape(g, p.x, p.y, currentNote);
int pitch = 12;
piano.playNote(pitch);
advance(1.0, piano);
try { addToFile(pitch, currentNote);}
catch(FileNotFoundException fnfe) {}
catch(IOException ioe) {}
}
// In the same class
protected String currentNote;
...
public void getShape(final Graphics g, final String note) {
currentNote = note;
}
I have a situation where I want something to be displayed when a user clicks on something in my UI (can be a grid, label, whatever). What I want is for a little box to be displayed that's similar to what's shown when a hover event is triggered. However, I only want to show it on a click, not a hover. Is there a way to do this without a lot of trouble? I know I could always create a little pop up Window but the hover text is exactly what I need and handles the location of the popup intelligently (which I think would take a good deal more work using a Window).
I don't think there's a simple way to do this. Here's the smart popup class we use:
public class SmartPopup extends PopupPanel {
public void show(int left, int top) {
setPopupPositionAndShow(new PositionCallback() {
#Override
public void setPosition(int offsetWidth, int offsetHeight) {
int popupLeft = left;
if ((offsetWidth + left > Window.getClientWidth())
&& (left - offsetWidth > 0)) {
popupLeft = left - offsetWidth;
}
int popupTop = top;
if ((top + offsetHeight > Window.getClientHeight())
&& (top - offsetHeight > 0)) {
popupTop = top - offsetHeight;
}
setPopupPosition(popupLeft, popupTop);
}
});
}
}
Once you have a class like that, you could extend it to have your tool-tip styles, automatically include a label, etc...
public class ToolTip extends SmartPopup {
public ToolTip(String message) {
addStyleName("tool-tip-css");
add(new Label(message));
}
}
And then, from there your code will be pretty simple:
yourButtonOrWhatever.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
ToolTip toolTip = new ToolTip("Hey, this is like a tool-tip for clicking!");
toolTip.show(event.getClientX(), event.getClientY());
}
});
I love writing classes so much that I'd probably even make a special subclass of ClickHandler so I didn't have to type those lines over and over again...
yourButtonOrWhatever.addClickHandler(new ToolTipHandler("Hey, this is like a tool-tip for clicking!"));
Why not using this click event handler
onClickTooltip(com.smartgwt.client.widgets.events.ClickEvent event) {
int x = event.getX();
int y = event.getY();
final Canvas w = new Canvas();
w.setRect(x,y,72,72);
w.setContents("I am Here");
w.draw();
}