I've created a component that basically is a JPanel fully covered with (non-editable) JTextAreas. I want a MouseListener to be fired everytime the JPanel area is being clicked on. I do want to add the Listener once to the JPanel instead of n times to the JTextAreas.
Is there a way to send the JTextAreas to background, so the JPanel is clicked "through" the JTextArea?
Note: With JLabels this works without anything special, the JPanels Listener is always fired, but I prefer JTextAreas, because of the linebreak.
With JLabels this works without anything special, the JPanels Listener is always fired
This is because by default a JLabel does not contain a MouseListener so the MouseEvent is passed up the parent tree until a component the does use a MouseListener is found.
In the case of a JTextArea a MouseListener is added to the text area so you can position the caret and select text etc. If you don't need all this functionality you can remove the MouseListener from each text area with code something like:
JTextArea textArea = new JTextArea(...);
MouseListener[] ml = (MouseListener[])textArea.getListeners(MouseListener.class);
for (int i = 0; i < ml.length; i++)
textArea.removeMouseListener( ml[i] );
However, since you have to do that for every text area, I would suggest it is easier to just add the MouseListener to each text area. You can share the same MouseListener with every text area.
There is a solution proposed here, but it might not fully work for your needs.
I don't know if there is a way around adding the listener n times, but if there is not, you could integrate the process cleanly in your code.
For example, with a dedicated method to add the JTextAreas:
public void addJTextArea(JTextArea tArea){
this.add(tArea, ...);
tArea.addMouseListener(this.listener);
}
Or even more transparently with an extended JTextArea:
public class ClickableTextArea extends JTextArea {
public ClickableTextArea(MouseListener listener){
super();
addMouseListener(listener);
}
}
Related
I have a JFrame named MainGUI. Inside of MainGUI I have passed three LinkedList ll1, ll2, ll3.
These LinkedList are full of data and I'm trying to just print one of them on the screen into my JPanel. I'm use to just doing a for loop and using System.out.println to print things out onto the screen.
So right now I have MainGUI which hosts three buttons.
New Tasks In Progress Tasks Completed Tasks
Each button has a different LinkedList ll1, ll2, ll3 etc.
I want to be able to click the button and have the data elements listed below in the JPanelI created which rests under the buttons.
Any help is deeply appreciated.
Since you provided no code, I assume you are having trouble understanding how LinkedList can interact in programs that have a GUI.
First off, when using buttons you always need to instruct them to do something when they are clicked by adding an ActionListener, as explained in this answer.
Secondly, if you want to add the list data to the JPanel, there are a few ways you can do it. A JList, or if you'd like the user to be able to copy and paste the data (I find it to be very handy), a JTextArea, ... Just make sure to call setEditable(false) in order to stop the user from fiddling with the data you provide. Considering a JTextArea, here's what that would look like, if ll1 contained Strings:
Adding somewhere that our JPanel contains a JTextArea:
JTextArea txtArea = new JTextArea();
txtArea.setEditable(false);
panel.add(txtArea);
Now, we order the button to do something when clicked:
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
txtArea.setText(null); //clear out old text
for(String str: ll1) {
txtArea.append(str+"\n");
}
panel.revalidate(); //repaint JPanel
}
});
This way, you can click the button as many times as you want. Note that if you add more content to ll1 after it is displayed it won't get visually updated by itself, you will always need to click the button again or look further into Listeners.
You can try adding a JTextArea or whichever JComponent that suits what you want to display to the JPanel that you want to display the data from. Write the data from your linked list to that JComponent using its method e.g. append() if you're using JTextArea.
Newbie here trying to make a simple GUI with JTabbedPane. I've looked through a lot of examples but have been unable to find a solution. Basically, I'm trying to print out a String to a JTextArea. While it seems very simple, I have been unable to get everything to work together. I understand the difference between local and global variables, but I think that is where my problem lies. Any guidance would be greatly appreciated. *Please note that we are unable to use a layout manager for this project.
The code below represents part of the tab that has the JButton and JTextArea.
//Text area that shows details. Scrolls.
JTextArea areaDeets = new JTextArea();
areaDeets.setBounds(65, 300, 250, 300 );
areaDeets.setText("");
JScrollPane scroll = new JScrollPane (areaDeets);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
panel2.add(areaDeets);
panel2.add(scroll);
areaDeets.addActionListener(new StopTest());
//Stop button--stops tests when pressed.
JButton stop = new JButton("Stop");
stop.setBounds(215, 650, 100, 40);
panel2.add(stop);
stop.addActionListener(new StopTest());
The code below is the method that calls the ActionListener.
//Panel 1 - Stop, shows that the test has been stopped
static class StopTest implements ActionListener{
public void actionPerformed(ActionEvent e){
String stop = "The test has been stopped";
areaDeets.setText(stop);
panel2.repaint();
}
}
Edit: Code does not compile. Eclipse says that I cannot call addActionListener on a JTextField.
You can pass the reference of the JTextArea to the constructor of the ActionListener:
public class StopTest implements ActionListener {
private JTextArea area;
public StopTest(JTextArea area) {
this.area = area;
}
public void actionPerformed(ActionEvent e) {
String stop = "The test has been stopped";
area.setText(stop);
}
}
One possible solution (guessing here due to limited information): don't make the StopTest class static. Rather make it a private inner non-static class or a stand-alone class. This will allow it access to non-static fields of your outer class.
Don't add an ActionListener to your JTextArea as this is not allowed and has no real meaning, since JTextAreas allow returns to be entered, and use this to start a new line in the JTextArea.
Other unrelated recommendations:
Also, as a general rule, you should avoid use of null layout as this makes for very inflexible GUI's that while they might look good on one platform look terrible on most other platforms or screen resolutions and that are very difficult to update and maintain.
Much better would be to use nested JPanels, each using its own layout manager, and then calling pack() on your JFrame after adding all components but prior to displaying it.
Never call setBounds(), setSize(), setPreferredSize() or any similar call on a JTextArea that goes inside of a JScrollPane as it will prevent the JScrollPane from working correctly within your JScrollPane due to your setting bounds. This will prevent the JTextArea from expanding when more lines are added, sometimes preventing display of the scrollbars, or if their displayed, preventing them from working properly. Better to set the JTextArea's viewable columns and rows via one of its constructors that has int parameters.
There's no need to call repaint() after setting the text of a JTextComponent such as a JTextArea, since the textarea's model will notify its view (the part that is rendered on the GUI) of changes, and the view will then automatically call repaint itself.
I add my customized panel onto JScrollPane. I also have another set of "tool" that will attach itself to my custom panel. The problem is, in these tool, it invokes attached.addMouseListener(this). Normally, everything would function well, but when I have it inside JScrollPane, it won't function at all. My deduction is JScrollPane never gives window focus to its child component. Is there a way to get this around without having to change my attachment procedure? I want my 'tool' to specifically attach to my custom panel, not the scrollpane.
I hope I have understood the problem.
What about adding a MouseListener to the JScrollPane and then dispatch the event to the JPanel?
Somenthing like this:
//JScrollPane Listener
public void mousePressed(MouseEvent me) {
jpanel.dispatchEvent(me);
}
It's a little bit tricky, but so you don't have to change the JPanel Listener.
Is it possible to use a single JPanel for multiple tab items in JTabbedPane?
EG:
JTabbedPanel tabs=new JTabbePanel();
JPanel panel=new JPanel();
JButton but=new JButton("TEXT");
but.addActionlistener(this);
panel.add(but)
tabs.add("First",panel);
tabs.add("Second",panel);
An ActionListener is added to the JTabbedPane to notify the program of tab changes (change cur_tab to tab number)
public void actionPerformed(..)
{ System.out.println("Now in "+cur_tab); }
The same component cannot be used for several tabs
taken from here
Sounds like you need a subclass of JPanel. Just create an abstract class that handles the complex layout and have the subclasses create the necessary GUI elements that are required.
If you are just inserting a single text box, button, etc, you may not even need subclasses per tab. Just create multiple instances of the base class and add the component you need.
New panels and other GUI items are relatively cheap. Performance issues in a Swing GUI are more likely to come from event handling or firing too many events rather than how complex or how many components it has. Make things easier to maintain and understand, then worry about performance.
if you'll create class that returns JPanel then yes that's possible
but Notice:
there are long time Bug that two Tabs can't contains same component schemas, with schemas I means for example one Tab contains JPanel + JTextField + JButton, but then second JPanel must contains another Numbers or Type of JComponents
unfortunatelly (nothing special) BugsDatabase isn't accesible in this moment
I had a panel with memory-intensive components on it which I only wanted to create one instance of, but change the behaviour of it using the attractive JTabbedPane.
I did it by creating empty panels for each tab, and a third panel that contains my (single) complicated components. On the StateChange event for the JTabbedPane, I remove the third panel from whichever of the first two it was in, and add it to whichever one is newly selected.
Bit hacky, but it works fine.
You are wrong.
Just set a panel on the first tab in function initComponents() like that:
p.add("1", MainPanel);
Then use:
p.add("2", p.getTabComponentAt(0));
Using this metode you will have the same component on 2 tabs.
You can use StateChanged Event to change actions in this tabs.
For example:
JTabbedPane p = (JTabbedPane)Tabbar;
int idx = p.getSelectedIndex();
if(idx==0){
Do something...
}
if(idx==1){
Do something different...
}
The following will allow you to add the same component with different titles to a JTabbedPane:
JTabbedPane tabbedPane = new JTabbedPane()
{
boolean adding = false;
#Override
public void removeTabAt(int index)
{
if(!adding)
{
super.removeTabAt(index);
}
}
#Override
public void insertTab(String title, Icon icon, Component component, String tip, int index)
{
adding = true;
super.insertTab(title, icon, component, tip, index);
adding = false;
}
};
class Deal implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
dl.setDeck();
dl.shuffle();
dl.firstDraw(pl);
for(Card c:pl.showHand())
panelplay.add(new JLabel(c.getImageIcon()));
panelplay.validate();
}
}
This is an event handler for a Jbutton. The method pl.showHand() returns a ArrayList of a user defined class 'Card'. Inserting a println() inside the loop shows the print, so the code is being executed but the Panel panelplay isnt showing card Images.
What about the existing labels on the panel? You don't remove them. I'm guessing you are using a FlowLayout and the labels just get added to the end of the panel so you don't see them.
So one solution is to use panel.removeAll() before adding the labels back to the panel. I then use:
panel.revalidate();
panel.repaint();
Or the better option as suggested earlier is to not replace the labels but just replace the Icons using the setIcon() method.
Do as Gilbert says, look at the Swing Tutorial part that concerns Labels.
JLabel has the following methods...
void setIcon(Icon)
Icon getIcon()
Also look at the SplitPaneDemo It does exactly what you want, you can even run it with JNLP to see.
You don't want to add the JLabel in the ActionListener.
You want to use an already added JLabel setText() method in the ActionListener.
You define all the Swing components once, when you create the GUI.