I am having an issue with my horizontal scroll bar demo. I am trying to move a custom message panel using the scroll bar. I used an anonymous listener and override the adjustmentValueChanged() method like so,
public void adjustmentValueChanged(AdjustmentEvent e){
System.out.println(e.getAdjustmentType());
if( e.getAdjustmentType() == AdjustmentEvent.UNIT_INCREMENT ) {
panel.moveLeft();
}
}
I am trying to get the AdjustmentEvent using e.getAdjustmentType() so I can properly handle the adjustment of the message panel. However, it is not working. I used System.out.println() method to print the adjustment type on my screen to see what the problem is but what I am not understanding is that no matter what part of the scroll bar I press (whether it is the unit increment, unit decrement, block increment, etc..) the value returned is 5? I am not sure what the issue is can someone please help.
public class ScrollBarDemo extends JFrame {
private JScrollBar scrollHort = new JScrollBar(JScrollBar.HORIZONTAL);
private JScrollBar scrollVert = new JScrollBar(JScrollBar.VERTICAL);
private MessagePanel panel = new MessagePanel("Welcom to Java bitch");
public static void main(String[] args) {
ScrollBarDemo frame = new ScrollBarDemo();
frame.setTitle("ScrollBarDemo");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public ScrollBarDemo() {
setLayout(new BorderLayout());
add(panel, BorderLayout.CENTER);
add(scrollHort, BorderLayout.SOUTH);
add(scrollVert, BorderLayout.EAST);
scrollHort.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
System.out.println(e.getAdjustmentType());
if (e.getAdjustmentType() == AdjustmentEvent.UNIT_INCREMENT) {
panel.moveLeft();
}
}
});
}
}
Run the following sample, the method to use is getValue().
public class ScrollBarDemo extends JFrame {
public ScrollBarDemo() {
setLayout( new BorderLayout());
final JScrollBar scrollHort = new JScrollBar( JScrollBar.HORIZONTAL );
add( scrollHort, BorderLayout.SOUTH );
scrollHort.addAdjustmentListener( e -> System.out.println( e.getValue()));
setLocationRelativeTo(null);
setDefaultCloseOperation( EXIT_ON_CLOSE );
pack();
setVisible(true);
}
public static void main( String[] args ) {
new ScrollBarDemo();
}
}
Related
I have made this simple text editor program but can't figure out how to change GUI component's properties while the program is running.
Suppose this is a part of my Text Editor's source code:
boolean wordwrap = false;
void mainFrame() {
frame = new JFrame("Text Editor");
textArea = new JTextArea(50,20);
textArea.setLineWrap(wordwrap);
and let's say I have an event source(JButton) added as Listener to change
textArea's .setLineWrap(boolean). Just like this:
public void actionPerformed(ActionEvent event) {
if(wordwrap) wordwrap = false;
else wordwrap = true;
textArea.setLineWrap(wordwrap);
frame.repaint();
}
But this code is not working!!. So, what is the correct way to update or edit a JAVA GUI component while the program is running ?
revalidate and validate()
will update the frame.
You do not need to use repaint().
Final Method:
public void actionPerformed(ActionEvent event) {
if(wordwrap) wordwrap = false;
else wordwrap = true;
textArea.setLineWrap(wordwrap);
frame.revalidate(); //is preferable but validate() also works.
}
You can either update the whole frame or just update the jComponent (insert TextArea instead of "frame".revalidate();)
Just FYI, after I got a chance to test it, it works fine without either the revalidate() or the repaint(). I suspect the problem was somewhere else in your code.
public class TestTextArea
{
private final static String testLine =
"This is some rather long line that I came up with for testing a textArea.";
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run()
{
gui();
}
} );
}
private static void gui()
{
JFrame frame = new JFrame();
final JTextArea textArea = new JTextArea();
JPanel span = new JPanel();
JButton toggle = new JButton( "Switch line wrap" );
toggle.addActionListener( new ActionListener()
{
#Override
public void actionPerformed( ActionEvent e )
{
textArea.setLineWrap( !textArea.getLineWrap() );
}
} );
for( int i = 0; i < 10; i++ )
textArea.append( testLine + testLine + "\n" );
span.add( toggle );
frame.add( span, BorderLayout.SOUTH );
frame.add( textArea );
frame.pack();
frame.setSize( 500, 500 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
I have a JFrame in which I remove and add components and each time I do this, I resize the frame accordingly. I added a Component Listener but of course it gets triggered both by the user resizing the window and also by my setSize() methods.
Is there any way to see from the ComponentEvent whether the user resized the window or I did through setSize()?
The posible solutions I found are:
1. Use a flag - boolean resizing - which I set to true before setSize() and to false after that.
2. Add a mouseDragged listener and compare sizes before and after the drag.
The second one is definitely not a good choice. The first one would work but I would like to know if I can find in a simple way whether the user is the one who resized the window or not.
I resize the frame accordingly
Whats wrong with using pack()?
I remove and add components and each time I do this,
Then this is where you should set your Boolean value:
programResize == true:
panel.add(...);
frame.setSize(...); // this should cause the ComponentListener to fire
// the ComponentListener would then use programResize == false;
Or a better option option could be:
component.removeComponentListener(...);
panel.add(...);
frame.setSize(...);
component.addComponentListener(...);
I like this approach better because all the logic based on the manual update is self contained in one place and there is no need to define a Boolean variable.
Is there any way to see from the ComponentEvent whether the user
resized the window or I did through setSize()?
yes it is, use boolean flag reseted by Swing Timer
in the case that user resized window then ComponentListener firing a new event per every pixel, bunch of events
by determine the contianer set(Xxx)Size is this event fired only once time
example about events from ComponentListner
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
public class ComponentEventDemo extends JPanel
implements ComponentListener, HierarchyListener,
ItemListener {
private JFrame frame;
private static final long serialVersionUID = 1L;
private JTextArea display;
private JLabel label;
private JButton button = new JButton("Change Size");
private String newline = "\n";
public ComponentEventDemo() {
display = new JTextArea();
display.setEditable(false);
JScrollPane scrollPane = new JScrollPane(display);
scrollPane.setPreferredSize(new Dimension(350, 200));
label = new JLabel("This is a label", JLabel.CENTER);
label.addComponentListener(this);
JCheckBox checkbox = new JCheckBox("Label visible", true);
checkbox.addItemListener(this);
checkbox.addComponentListener(this);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Dimension dim = frame.getPreferredSize();
if (!dim.equals(new Dimension(800, 600))) {
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
} else {
frame.setPreferredSize(new Dimension(400, 300));
frame.pack();
}
}
});
JPanel panel = new JPanel(new GridLayout(1, 3));
panel.add(label);
panel.add(checkbox);
panel.add(button);
panel.addComponentListener(this);
frame = new JFrame("ComponentEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(panel, BorderLayout.PAGE_END);
frame.pack();
frame.setVisible(true);
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
label.setVisible(true);
label.revalidate();
label.repaint();
} else {
label.setVisible(false);
}
}
protected void displayMessage(String message) {
//If the text area is not yet realized, and
//we tell it to draw text, it could cause
//a text/AWT tree deadlock. Our solution is
//to ensure that the text area is realized
//before attempting to draw text.
// if (display.isShowing()) {
display.append(message + newline);
display.setCaretPosition(display.getDocument().getLength());
//}
}
#Override
public void componentHidden(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
}
#Override
public void componentMoved(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Moved");
}
#Override
public void componentResized(ComponentEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Resized ");
}
#Override
public void componentShown(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Shown");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ComponentEventDemo componentEventDemo = new ComponentEventDemo();
}
});
}
#Override
public void hierarchyChanged(HierarchyEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Hierarchy changed");
}
}
They are actually two questions:
The First question:
What is the difference between getValueIsAdjusting() in both JScrollBar and of AdjustmentEvent
I tried them with some code to test if any difference, but I didn't get any!. Here is the code to show How I tested them.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ScrollTest extends JPanel
{
JPanel panel;
JScrollBar scroll;
public ScrollTest()
{
scroll = new JScrollBar(JScrollBar.HORIZONTAL, 0, 6, 0, 300);
scroll.addAdjustmentListener(ScrollListener);
panel = new JPanel(new GridLayout(1, 0));
panel.add(scroll);
this.setLayout(new BorderLayout());
this.add(panel);
}
AdjustmentListener ScrollListener = new AdjustmentListener()
{
#Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
if(e.getValueIsAdjusting())
{
System.out.println("AdjustmentEvent");
}
if(scroll.getValueIsAdjusting())
{
System.out.println("JScrollBar");
}
}
};
private static void createAndShowGUI()
{
JFrame frame;
frame = new JFrame("Scroll Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(880, 100);
frame.add(new ScrollTest(), BorderLayout.CENTER);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
The code above will print "AdjustmentEvent" and "JScrollBar" strings in sequence. it seems there is no difference between them!
The important point is when/for what to use each?
The Second question:
How to listen to JScrollBar buttons? if you tested the above code, it prints the strings when you move the knob or click on the strip, but not when you click the buttons of the JScrollBar!
Add one more event (as stated here) in the adjustmentValueChanged of AdjustmentListener class.
If event type is AdjustmentEvent.TRACK then also print a statement.
if(e.getValueIsAdjusting())
{
System.out.println("AdjustmentEvent");
}
if(scroll.getValueIsAdjusting())
{
System.out.println("JScrollBar");
}
if(e.getAdjustmentType() == AdjustmentEvent.TRACK)
{
System.out.println("The button in scrollbar clicked");
}
This will capture the button click action on the JScrollBar.
Good evening ladies and gentlemen,
I have a problem with Java Swing that I cannot solve, maybe you can help me. Here it is:
I have one JFrame which uses BorderLayout, and many JPanels.
Every time I need to put up a new screen (i.e. from the Main Menu, when Search button is clicked, go to the Search Menu), I simply remove the component (JPanel) which is located in the center, and put the new screen (new JPanel) in the center instead.
This way, I don't call all my header and footer objects every time I want to put up a new screen.
Everything works fine with this system except this little problem: I want to trigger some methods everytime I put up a new JPanel or change back to an existing JPanel (generally speaking, everytime a JPanel appears).
In order to do that, I tried to implement ComponentListener's componentShown(ComponentEvent e) method, and added a ComponentListener to a JPanel which I put up in the center of my JFrame, and it did NOT work. After this, I did some research and found out that this componentShown (#ComponentListener) method only works when the visibilty of the JPanel is changed (from invisible to visible or the opposite). Unfortunately, I'm not changing the visibility of a JPanel, just replacing it with another one: removing the current one, and adding the new one. Below code illustrates how I replace the JPanels.
// Get the JPanel located in the center of our JFrame
JPanel currentView = (JPanel) myFrame.getContentPane().getComponent( 2 );
if ( currentView != null )
{
// Remove it from the JPanel
myFrame.getContentPane().remove( currentView );
}
// Add the new JPanel
myFrame.getContentPane().add( otherView, BorderLayout.CENTER );
// Pack the JFrame and show it
myFrame.pack();
So here is what I have. I would really appreciate it if you could help me out.
I think that this issue corresponding with HierarchyListener, for comparing
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ContainerListener extends JFrame {
private static final long serialVersionUID = 1L;
public ContainerListener() {
super("Test");
setContentPane(new TestPanel());
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] parameters) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ContainerListener containerListener = new ContainerListener();
}
});
}
private class TestPanel extends JPanel {
private static final long serialVersionUID = 1L;
TestPanel() {
setLayout(new FlowLayout(FlowLayout.LEFT));
add(new JButton(new AbstractAction("Add label") {
private static final long serialVersionUID = 1L;
private int n = 0;
#Override
public void actionPerformed(ActionEvent event) {
TestPanel.this.add(new JLabel("Label " + ++n));
validate();
}
}));
addHierarchyListener(new HierarchyListener() {
#Override
public void hierarchyChanged(HierarchyEvent e) {
System.out.println("Components Change: " + e.getChanged());
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
if (e.getComponent().isDisplayable()) {
System.out.println("Components: " + e.getChanged());
} else {
System.out.println("Components: " + e.getChanged());
}
}
}
});
addContainerListener(new ContainerAdapter() {
#Override
public void componentAdded(ContainerEvent event) {
System.out.println("componentAdded : " + event.getChild() + "containerName" + " was added");
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
I highly recommend listening to the advice given by #Jeffrey, but if you do proceed with this design, then perhaps implementing the ContainerListener interface may prove useful.
When in doubt, consult the API.
I Have two files. One extends JFrame, and another Extends JPanel.
Whenever I change the size of the frame, whether it be maximizing, dragging, whatever, i want the ScrollPane to fit itself to the current size of the frame.
There's more to it, there's a top menubar and a bottom bar as well, but i left those out for simplicity.
Essentially, i want it to work like notepad.
right now, I use a ComponentListener on the frame that calls a setSize method in the the other class.
The setSize method is just:
public void resize(int x, int y)
{
textA.setPreferredSize(new Dimension(x, y-50));
areaScrollPane.setPreferredSize(new Dimension(x,y-50));
}
also, for reference:
public void componentResized(ComponentEvent e)
{
textA.resize(panel.getWidth(),panel.getHeight());
}
FYI, it extends JPanel because of the way I add it to the frame:
panel = (JPanel) this.getContentPane();
panel.setLayout(new BorderLayout());
panel.add(textA, BorderLayout.CENTER);
so what's the best way to do this?
Thanks!
Edit: Here's the scrollpane file. It's called textA in my main.
public class TextArea extends JPanel
{
JTextArea textA=new JTextArea(500,500);
JScrollPane areaScrollPane = new JScrollPane(textA);
Toolkit toolkit = Toolkit.getDefaultToolkit ();
Dimension dim = toolkit.getScreenSize();
Dimension dim2=(new Dimension((int)(dim.getWidth()),(int)(dim.getHeight()-120)));
public TextArea()
{
//textA.setLineWrap(true);
//textA.setWrapStyleWord(true);
textA.setEditable(true);
textA.setForeground(Color.WHITE);
textA.setBackground(Color.DARK_GRAY);
this.setFont(null);
areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
areaScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
areaScrollPane.setMinimumSize(new Dimension(300,300));
areaScrollPane.setSize(new Dimension(800,800));
textA.setPreferredSize(dim2);
areaScrollPane.setPreferredSize(dim2);
areaScrollPane.setMaximumSize(dim2);
add(areaScrollPane);
}
#Override
public void resize(int x, int y)
{
textA.setPreferredSize(new Dimension(x, y-50));
areaScrollPane.setPreferredSize(new Dimension(x,y-50));
}
}
and the main:
public class JEdit extends JFrame implements ComponentListener
{
TextArea textA=new TextArea();
JPanel panel;
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
JEdit run=new JEdit();
}
public JEdit()
{
setTitle("JEdit");
setLayout(new BorderLayout());
setSize(1100, 1000);
this.setMinimumSize(new Dimension(100,100));
//setBackground(Color.BLACK);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
System.out.println("error1");
} catch (InstantiationException ex) {
System.out.println("error2");
} catch (IllegalAccessException ex) {
System.out.println("error3");
} catch (UnsupportedLookAndFeelException ex) {
System.out.println("error4");
}
panel = (JPanel) this.getContentPane();
panel.setLayout(new BorderLayout());
//TopBar top=new TopBar();
// PositionBar posB=new PositionBar();
panel.add(textA, BorderLayout.CENTER);
// add(top,BorderLayout.NORTH);
// add(posB,BorderLayout.SOUTH);
addComponentListener(this);
setVisible(true);
}
public void componentResized(ComponentEvent e)
{
textA.resize(panel.getWidth(),panel.getHeight());
}
public void componentMoved(ComponentEvent e) {
textA.resize(panel.getWidth(),panel.getHeight());
}
public void componentShown(ComponentEvent e) {
textA.resize(panel.getWidth(),panel.getHeight());
}
public void componentHidden(ComponentEvent e) {
textA.resize(panel.getWidth(),panel.getHeight());
}
}
Regarding the code you've posted, for one get rid of all calls to setSize -- these are generally not honored when using layout managers and get rid of all of your ComponentListener stuff as it's superfluous since you are using layout managers to resize things. The biggest problem I see though is that your allow your TextArea JPanel to use its default layout, which is FlowLayout, and doing so will prevent the JScrollPane that it holds from resizing. Give this class a BorderLayout (or better simply return a JScrollPane from the class), and you're set. e.g. with quick modifications and with renaming of classes to prevent clashes with the standard Java classes,
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class JEdit2 extends JFrame {
TextArea2 textA = new TextArea2();
JPanel panel;
public static void main(String[] args) {
new JEdit2();
}
public JEdit2() {
setTitle("JEdit 2");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = (JPanel) this.getContentPane();
panel.add(textA, BorderLayout.CENTER);
pack(); //!! added
setLocationRelativeTo(null);
setVisible(true);
}
}
#SuppressWarnings("serial")
class TextArea2 extends JPanel {
JTextArea textA = new JTextArea(500, 500); // !! this is one friggin' huge JTextArea!
JScrollPane areaScrollPane = new JScrollPane(textA);
public TextArea2() {
textA.setEditable(true);
textA.setForeground(Color.WHITE);
textA.setBackground(Color.DARK_GRAY);
this.setFont(null);
setLayout(new BorderLayout()); //!! added
add(areaScrollPane, BorderLayout.CENTER);
}
}
By default a JFrame uses a BorderLayout (so there is no need to reset it). All you need to do is add the JScrollPane to the CENTER of the BorderLayout and it will resize automatically.
And the basic code would be:
JTextArea textArea = new JTextArea(...);
JScrollPane scrollPane = new JScrollPane();
frame.add(scrollPane, BorderLayout.CENTER);
I'm not sure why you are adding the text area to the center.
There is no need to use setPreferredSize() on any component or use a listener on any component.
If you need more help then you need to post a SSCCE.