I'm developing a small photo editing application and would like the JButtons disabled until the user loads an image, at which point I want the buttons to become enabled(clickable). My thinking was to add a boolean imageFound, and an image checker method. If boolean is false, the buttons are disabled and if it is true they are enabled (the boolean is set to true in the load image actionPerformed method). The problem im having is that when running the app, the buttons are disabled as they should be, but when i load the image they would still be disabled. I dont know if maybe i am missing any piece of code to recheck whether the image is available, thus enabling the buttons (at runtime ofc). Thanks for any help.
...BufferedImage effects = null;
boolean bmpFound = false;
public GUI()
{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.initComponents();
this.bmpChecker();
this.addListeners();
this.setTitle("PicTweak");
this.setSize(900, 600);
this.setVisible(true);
}
...else if(e.getSource() == loadItem)
{
try
{
imagePath = DialogIO.displayOpenDialog();
effects = ImageInOut.loadImage(imagePath);
imageHolder.setIcon(new ImageIcon(effects));
bmpFound = true;
}
....public void bmpChecker()
{
if(bmpFound)
{
grayScale.setEnabled(true);
blur.setEnabled(true);
reset.setEnabled(true);
brightDark.setEnabled(true);
horFlip.setEnabled(true);
verFlip.setEnabled(true);
verHorFlip.setEnabled(true);
}
else
{
grayScale.setEnabled(false);
blur.setEnabled(false);
reset.setEnabled(false);
brightDark.setEnabled(false);
horFlip.setEnabled(false);
verFlip.setEnabled(false);
verHorFlip.setEnabled(false);
}
}
When you load/unload the image, call bmpChecker() afterwards, i.e.
...
try
{
imagePath = DialogIO.displayOpenDialog();
effects = ImageInOut.loadImage(imagePath);
imageHolder.setIcon(new ImageIcon(effects));
bmpFound = true;
bmpChecker();
}
...
A better alternative would be t add listeners for the image loading, i.e. for each control or group of controls that needs to update its state accordingly, you'd register a listener that is notified whenever an image is loaded or unloaded. The listener could then trigger the updates of the corresponding controls.
Something like:
class ImageEvent {
private boolean imageLoaded; //plus getter/setter and maybe initialized in constructor
}
interface ImageListener {
void imageChanged(ImageEvent e);
}
...
List<ImageListener> listeners;
...
try
{
imagePath = DialogIO.displayOpenDialog();
effects = ImageInOut.loadImage(imagePath);
imageHolder.setIcon(new ImageIcon(effects));
bmpFound = true;
ImageEvent imgageEvent = new ImageEvent();
imageEvent.setImageLoaded(true);
for( ImageListener l : listeners ) {
l.imageChanged(imageEvent);
}
}
...
And an example listener:
class JButtonImageListener implements ImageListener {
private JButton button; //plus getter/setter
public void imageChanged(ImageEvent e) {
button.setEnabled(e.isImageLoaded());
}
}
Related
I've set a JTextField visibility to false, and when I click a button it is supposed to immediately show but it doesn't until I resize the window.
I'm building a login/'sign up' app using Swing containing tree text fields (Username, password and confirm password (which visibility is set to false until I press the signup button). But the text field does not appear until I resize the window and I can't seem to figure out what the problem is. I used the same 'code structure' as I did in another project, and didn't have any problem at all.
You can see the code below:
setTxtusername(new JTextField("Entrez username",20));
getTxtusername().setVisible(true);
setTxtpassword(new JTextField("Entrez Password",20));
getTxtpassword().setVisible(true);
setTxtconfirmer(new JTextField("Confirmer Password",20));
getTxtconfirmer().setVisible(false);
setBtnlogin(new JButton("Login"));
getBtnlogin().setVisible(true);
getBtnlogin().addActionListener(l);
getBtnlogin().setActionCommand("login");
setBtnsignup(new JButton("Sign up"));
getBtnsignup().setVisible(true);
getBtnsignup().addActionListener(l);
getBtnsignup().setActionCommand("Signup");
//Hb is an horizontal box and Vb is a vertical one
getHb2().add(btnlogin);
getHb2().add(btnsignup);
getHb2().add(warninglabel);
getHb2().setVisible(true);
getVb().add(txtusername);
getVb().add(txtpassword);
getVb().add(txtconfirmer);
getVb().add(hb2);
getVb().setVisible(true);
pnl.add(vb);
pnl.setVisible(true);
Here is the ActionListener
public class Listener implements ActionListener{
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String action = e.getActionCommand().toString();
switch(action){
case "login":
break;
case "Signup":
ConfirmerVisible(true, txtconfirmer);
conteneur.revalidate();
creationCompte();
break;
}
}
public void creationCompte() {
if(getTxtconfirmer().getText().length() >=6 && getTxtpassword().getText() == getTxtconfirmer().getText()) {
if(admin.isSelected()) {
Utilisateur u = new Utilisateur(txtusername.getText(), getTxtpassword().getText(), 1);
//Connexionuser.create(u);
//Connexionuser.login(u)
}
}
}
}
private void ConfirmerVisible(boolean b, Component c) {
c.setVisible(b);
}
}
To refresh GUI Use:
revalidate();
repaint();
I guess once you doing "resize" it's triggered automatically by JFrame and recursively triggering refresh on child components also.
I'm using the StyledEditorKit in a project I'm working on. I've used the StyledEditorKit.BoldAction(), and the StyledEditorKit.ItalicAction(). Now I want to use the StyledEditorKit.UnderlineAction() as well.
I make the JButtons that they'll be used in:
JButton bold = new JButton(new StyledEditorKit.BoldAction());
tool.add(bold);
JButton italic = new JButton(new StyledEditorKit.ItalicAction());
tool.add(italic);
JButton underline = new JButton(new StyledEditorKit.UnderlineAction());
tool.add(underline);
They each have their own use where I setText(null) and assign an Icon to the button. Then when I try to use these buttons in an AbstractAction:
Action Bold = new AbstractAction("Bold", new ImageIcon("bold.png"))
{
public void actionPerformed(ActionEvent e)
{
if(bolded == false)
{
area.setFont(area.getFont().deriveFont(Font.BOLD));
bolded = true;
}
else
{
area.setFont(area.getFont().deriveFont(Font.PLAIN));
bolded = false;
}
}
};
Action Italic = new AbstractAction("Italic", new ImageIcon("italic.png"))
{
public void actionPerformed(ActionEvent e)
{
if(italiced == false)
{
area.setFont(area.getFont().deriveFont(Font.ITALIC));
italiced = true;
}
else
{
area.setFont(area.getFont().deriveFont(Font.PLAIN));
italiced = false;
}
}
};
Action underline = new AbstractAction("underline", new ImageIcon("underline.png"))
{
public void actionPerformed(ActionEvent e)
{
if(underlined == false)
{
area.setFont(area.getFont().deriveFont(Font.UNDERLINE));
underline = true;
}
else
{
area.setFont(area.getFont().deriveFont(Font.PLAIN));
underline = false;
}
}
};
The first two AbstractActions work fine. The final one where I use
area.setFont(area.getFont().deriveFont(Font.UNDERLINE);
is not correct however. I have yet to find the actual implementation on oracle (am I looking in the wrong place maybe?), but I figure it is just how I am using 'UNDERLINE' that is incorrect. Simple answer I know. Any help is appreciated.
I figured it out. Yeah that second half of code is completely unnecessary.
The StyledEditorKit that was called in the creation of the button was all I needed to get it working. When I was trying to implement that second AbstractAction, something was going on that wasn't happening in the other 2 AbstractActions (for what ever reason).
I was under the impression I still needed to create another bold action in order to bold the text, but Java handles all of that automatically with the StyledEditorKit.
I have 2 classes, one class is a JFrame (MainUIHolder.java) and the other class is a JDialog (EditValuationsDialog.java). MainUIHolder can call EditValuationsDialog on button click event.
Once EditValuationsDialog is open, user can enter data in its fields and press its "Add" button. OK, here is the issue now. Once the user press the "Add" button, the EditValuationsDialog should inform that to the MainUIHolder.
Below is the code.
MainUIHolder
Action edit = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
JTable table = (JTable)e.getSource();
int rowNum = Integer.valueOf(e.getActionCommand());
Object valueAt = table.getModel().getValueAt(rowNum, 0);
EditValuationsDialog edit = new EditValuationsDialog(null,true);
edit.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
edit.setTitle("Edit Valuations");
edit.setClientName(portfolioViewClientName.getText());
edit.setPortfolioType(portfolioViewInvestmentTypeCombo.getSelectedItem().toString());
edit.setPortfolioId(id);
edit.setOngoingValuationsId(Integer.parseInt(String.valueOf(valueAt)));
edit.setLocationRelativeTo(table);
edit.setVisible(true);
//CATCH THE CALL FROM EditValuationsDialog HERE!!!!//
}
};
EditValuationsDialog
//Action Listeners
private class AddBtnAction implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(someCondition)
{
return String / int to MainUIHolder (See where I want to catch it in MainUIHolder)
}
else
{
do nothing
}
}
}
In my code I have indicated from where the call to MainUIHolder should be generated and in what place I must catch that call in MainUIHolder. How can I do this call back work?
You could...
Add a static method to EditValuationsDialog that shows the dialog, evaluates the results and returns the value you are expecting...
public void actionPerformed(ActionEvent e)
{
int result = EditValuationsDialog.showDialog();
}
public class EditValuationsDialog ... {
//...
private int result = -1;
//...
public int getResult() {
return result;
}
//...
public static int showDialog(Component source, int rowNum, Object valueAt) {
EditValuationsDialog edit = null;
Window parent = SwingUtilities.windowFor(source);
if (parent instanceof Frame) {
edit = new EditValuationsDialog((Frame)parent,true);
} else if (parent instanceof Dialog) {
edit = new EditValuationsDialog((Dialog)parent,true);
} else {
edit = new EditValuationsDialog(null,true);
}
edit.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
edit.setTitle("Edit Valuations");
edit.setClientName(portfolioViewClientName.getText());
edit.setPortfolioType(portfolioViewInvestmentTypeCombo.getSelectedItem().toString());
edit.setPortfolioId(id);
edit.setOngoingValuationsId(Integer.parseInt(String.valueOf(valueAt)));
edit.setLocationRelativeTo(source);
edit.setVisible(true);
return edit.getResult();
}
//...
private class AddBtnAction implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
if(someCondition)
{
result = 0;
}
else
{
result = 1;
}
EditValuationsDialog.this.dispose();
}
}
}
Or you could...
Simply evaluate the results of getResult() from the above example directly...
Side note: Because I don't like extending from top level containers like JDialog, I tend to create some of my panels/components with static showDialog methods, thing something along the lines of a login panel for example. It means I could re-use the panel else where, but provides me with the convenience of been able to popup a dialog when I need to. I've also used JOptionPane from time to time to show these panels, but it depends on the complexity of the available actions...
Make the dialog modal (setModal(true)). Then the code after dialog.setVisible(true) is executed after the dialog is closed.
BTW it's better to pass the MainUIHolder JFrame instance as parent of the dialog.
You could add an interface to the EditValuationsDialog something like this:
Interface EditValuationsDialogInterface {
public void onAddClicked(addedVlue);
}
and then add it as such:
edit.setOnAddButtonCallback(new EditValuationsDialogInterface () {
#Override
onAddClicked(addedVlue){
//DO SOMETHING
}
});
in your EditValuationsDialog's add button onclick call add this:
onAddButtonClickedCallback.onAddClicked(retunrValue);
This allows you to have a direct link back to the original calling class.
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 am just wondering...
When I click refresh button my gwt app comes to its default UI state despite its UI was modified during client-server interactions (callbacks) etc... But sometimes it is really essential thing to "cache" UI if user clicks refresh by mistake or reopened web page which user still logged-in;
So my question is...
Is there a way to restore gwt app UI (its before-refreshed state) in some standard way? Can History tokens help for this kind of issue?
edit
Concerning the history tokens I saw this example :
History.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
// Parse the history token
try {
if (historyToken.substring(0, 4).equals("page")) {
String tabIndexToken = historyToken.substring(4, 5);
int tabIndex = Integer.parseInt(tabIndexToken);
// Select the specified tab panel
tabPanel.selectTab(tabIndex);
} else {
tabPanel.selectTab(0);
}
} catch (IndexOutOfBoundsException e) {
tabPanel.selectTab(0);
}
}
});
... and I could notice it restores tabIndex from history; so will it help if tab panel won't be init-ed by module load (by default) but something this way:
//on button click...
getSimplePanel().setWidget(new MyTabbedPane());
edit
To be more clear here is my test code which I am trying to figure out how to restore MainUI I mean its previous UI state as if refresh button wasn't clicked.
the EntryPoint...
public class Main implements EntryPoint {
private SimplePanel simplePanel;
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
FlowPanel flowPanel = new FlowPanel();
rootPanel.add(flowPanel, 10, 10);
flowPanel.setSize("410px", "280px");
Button setWidgetButton = new Button("Click");
setWidgetButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getSimplePanel().setWidget(new MainUI());
}
});
flowPanel.add(setWidgetButton);
simplePanel = new SimplePanel();
flowPanel.add(simplePanel);
}
protected SimplePanel getSimplePanel() {
return simplePanel;
}
}
...and composite;
public class MainUI extends Composite {
private VerticalPanel verticalPanel;
int index;
public MainUI() {
FlowPanel flowPanel = new FlowPanel();
initWidget(flowPanel);
Button button = new Button("+");
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getVerticalPanel().add(new Label(""+(++index)+": "+Math.random()));
}
});
flowPanel.add(button);
DecoratorPanel decoratorPanel = new DecoratorPanel();
flowPanel.add(decoratorPanel);
verticalPanel = new VerticalPanel();
decoratorPanel.setWidget(verticalPanel);
}
protected VerticalPanel getVerticalPanel() {
return verticalPanel;
}
}
...and, as a result, to have "cached" ui state without regenerating it again with extracting strings from history tokens and re-instantiate objects or what so ever...
for example if I have this UI (see image) I am interested to have totally the same one after refresh button is pressed...
but I am not pretty sure which way should I look for? I haven't seen any gwt snippet in this direction; So I really need your advice what way should I dig in?
Any useful comment is appreciated
Thanks
P.S. GWT 2.3
I think you miss to store the state into the URLs-Hashtag.
You can use GWTP (as suggested in the comments)
In fact you need to read the Hashtag in your onModuleLoad and restore your state.
This may work with getHash():
String state = Window.Location.getHash();
myRestoreStateFromTokenMethod(state);
update
Here are some snippets to create a push store.
List<String> states = [...]
public void onClick(){ states.add("newState");changeHash(states); }
public void changeHash(){
String hash = states.get(0) + ";"
for(other states) hash += states.get(i);
// use a UrlBuilder to set the Hash
}
Documentation for UrlBuilder
Or you can try this: https://github.com/jbarop/gwt-pushstate