How to move JSplitPane's divider when I double-clicked it? - java

I want to move JSplitPane's divider to center if I double-click the divider.
So I added MouseListener to JSplitPane but it didn't work.
It works only when I double-clicked other JSplitPane's space without the divider.
Is there any way to work as I want?
Here is the code I failed
splitPane.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
//super.mouseClicked(e);
splitPane.setDividerLocation(0.5);
}
});
(it work same when I use MouseListener)

The reason your code doesn't work is that the JSplitPane itself does not recieve the click event.
Instead, the UI class of JSplitPane does.
This code works:
JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, component1, component2);
SplitPaneUI spui = split.getUI();
if (spui instanceof BasicSplitPaneUI) {
((BasicSplitPaneUI) spui).getDivider().addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
if (arg0.getClickCount() == 2) {
split.setDividerLocation(0.5);
}
}
});
}

Related

Java Swing JScrollPane not scrolling when shift held down and using mouse wheel

I have a simple Java Swing program defined below:
import javax.swing.*;
import java.awt.*;
public class Test implements Runnable {
public static void main(String[] args) {
Test main = new Test();
SwingUtilities.invokeLater(main);
}
#Override
public void run() {
// Application window.
JFrame mainFrame = new JFrame();
// Set up window.
mainFrame.setPreferredSize(new Dimension(600,700));
mainFrame.setFocusable(true);
mainFrame.requestFocus();
JScrollPane scrollPane = new JScrollPane();
scrollPane.setPreferredSize(new Dimension(600,700));
JPanel scrollPanel = new JPanel();
scrollPanel.setLayout(new GridLayout(0,1));
// Add buttons.
for (int i = 0; i < 40; i ++) {
JButton button = new JButton("Button " + i);
button.setPreferredSize(new Dimension(600,100));
scrollPanel.add(button);
}
scrollPane.setViewportView(scrollPanel);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel mainPanel = new JPanel();
mainPanel.add(scrollPane);
// Fill up window.
mainFrame.getContentPane().setLayout(new BorderLayout());
mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER);
SwingUtilities.updateComponentTreeUI(mainFrame);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setVisible(true);
}
}
The program consists of a simple JScrollPane with multiple buttons inside of it. Only vertical scrolling is enabled. It works fine.
However, the problem is, when I am holding down the 'shift' key, vertical scrolling does not work when I am using the mouse wheel to scroll. Vertical scrolling only works when I drag the scrollbar or let go of the 'shift' key.
Usually, in a JScrollPane, when the 'shift' key is held down, and the mouse wheel is used, it scrolls horizontally instead of vertically. However, I have disabled horizontal scrolling.
How would I go about enabling vertical scrolling using the mouse wheel if the user is holding down 'shift'?
I don't think there is a simple way to do this because normally you would only need the shift scroll when scrolling in more than one direction.
You could try adding a key listener to your JFrame and setting the wheel on your mouse to scroll vertically whenever the shift key is pressed. I tried it with this code and it worked just fine:
frame.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
if(arg0.isShiftDown()) {
frame.addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent arg0) {
// TODO Auto-generated method stub
pane.getVerticalScrollBar().setValue(pane.getVerticalScrollBar().getValue()+arg0.getWheelRotation());
}
});
}
if(!arg0.isShiftDown()) {
frame.removeMouseWheelListener(frame.getMouseWheelListeners()[0]);
}
}
}
I have figured out a cleaner and simpler answer to my question. Here is the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class CustomScrollPane extends JScrollPane {
public CustomScrollPane(Component component) {
super(component);
initialize();
}
private void initialize() {
// Set up the scroll bar.
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// Disable scrolling so we can do it manually.
setWheelScrollingEnabled(false);
addMouseWheelListener(new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
// Manually scroll.
getVerticalScrollBar().setValue(getVerticalScrollBar().getValue() + (e.getWheelRotation()));
}
});
}
}
The solution involves disabling JScrollPane from scrolling. It detects when the mousewheel is being rotated, and manually scrolls. This way, it will scroll when the mousewheel is rotated; it does not matter if 'shift' is being held down or not. The only drawback that I can see is that getVerticalScrollBar().setUnitIncrement() will not change the scrolling speed. The scrolling speed has to be changed manually, perhaps with a constant multiplier.

could not remove/add jpanel in jframe

I'm stuck with an issue that is, I have a JFrame with 2 JPanels added in it as showed in Figure :
in figure above, one JPanel have some JButtons and second JPanel have some form fields, I want to change/(remove old and add new JPanel) when I click on JButtons in first JPanel accordingly as shown bellow :
I have code snippet :
myPanel.clickListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
MainFrame.this.getContentPane().remove(((BorderLayout)getLayout()).getLayoutComponent(BorderLayout.CENTER));
MainFrame.this.getContentPane().add(twoPanel, BorderLayout.CENTER);
MainFrame.this.invalidate();
MainFrame.this.validate();
}
});
myPanel.clickListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
MainFrame.this.getContentPane().remove(((BorderLayout)getLayout()).getLayoutComponent(BorderLayout.CENTER));
MainFrame.this.getContentPane().add(customerPanel, BorderLayout.CENTER);
MainFrame.this.invalidate();
MainFrame.this.validate();
}
});
MainFrame.this.setMaximumSize(new Dimension(600, 550));
MainFrame.this.setMinimumSize(new Dimension(599, 549));
MainFrame.this.setSize(600, 550);
MainFrame.this.setResizable(false);
MainFrame.this.setVisible(true);
}
});
through above code I'm able to add new JPanel but unable to remove first JPanel.
in my opinion you should use CardLayout.
It allows you to change visibility of JPanel, so that is actually what you want to do.
You define two JPanels for the right side and then in listner just toggle them.
Look here for the example:
https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html

Undecorated button: JButton or JLabel with MouseListener?

I want to implement a button that does not show borders or anything else, except for an image that changes when you hover over it. Clicking on the image (showing the hover image) will execute some code.
I also would like to put all this in a separate class so I have a reusable component.
Extending a JButton delivers me the methods addActionListener() and so forth. But using the setAction() method removes the images that I set in the constructor. So it's not watertight, as I cannot use an Action in combination with this class. And I certainly do not want to override method like setAction().
public class JHoverLabel extends JButton {
private final Icon normal;
private final Icon hovered;
public JHoverLabel (Icon normal, Icon hovered) {
this.normal = normal;
this.hovered = hovered;
setIcon(normal);
setFocusPainted(false);
setMargin(new Insets(0, 0, 0, 0));
setContentAreaFilled(false);
setBorderPainted(false);
setOpaque(false);
addMouseListener(new HoverListener());
}
private class HoverListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {
setIcon(hovered);
}
#Override
public void mouseExited(MouseEvent e) {
setIcon(normal);
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
}
}
Extending a JLabel seems to do what a want in combination with a MouseListener, but I feel like using the wrong component here, because 'click-on-me-to-do-something' basically leads me to a JButton.
So what should I use? A JLabel or a JButton?
use implemented methods for JButton.setXxxIcon
button.setRolloverIcon((Icon));
button.setPressedIcon(Icon);
button.setDisabledIcon(Icon);
instead of MouseListener you can implements ButtonModel
So what should I use? A JLabel or a JButton?
Use a JButton. Your mouse challenged users will thank you.

JSplitPane Resize Cursor

I can't seem to change the resize cursor of JSplitPane by calling setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); Does anyone know how to get around this? I am using Nimbus UI.
Calling setCursor on a JSplitPane component will set the cursor only for left & right (or top & bottom) components.
To set the cursor for the divider component, you can use:
Component divider = ((BasicSplitPaneUI)splitPane.getUI()).getDivider();
divider.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
We can add code for mouse listener in addPropertyChangeListener() listener of JSplitPane and after loading of GUI we can fire this event to bind mouse listener to divider. Here is my code:
splitPanehor.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, (pce) -> {
Component divider1 = ((JSplitPane) pce.getSource()).getComponent(2);
divider1.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
ExomDataGUI.f.setCursor(new Cursor(Cursor.W_RESIZE_CURSOR));
}
#Override
public void mouseExited(MouseEvent e) {
ExomDataGUI.f.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
});
});
And we can fire this event after showing GUI in following way:
splitPanehor.firePropertyChange(JSplitPane.DIVIDER_LOCATION_PROPERTY, 219, 220);

Programming a GUI with resizable components using Java.swing

I'm supposed to program a GUI. Every component in this GUI has to have the possibility to be resized dynamically.
So far I worked with GlassPane and ContentPane, added a JPanel and on it a button. When clicking the GlassPane gets the event, analyses the underlying component, creates a new handle for this special component and handles it over to the said component.
I added a button that should change its size automatically. Works like I wanted it to work.
BUT: When I change the size of the frame and click on the button now, nothing happens. The GlassPane is able to identify the button, but something seems to be wrong...
Here's the code for the interception of GlassPane and giving the event to the component:
private void resendEvent(MouseEvent e) {
//Point p = SwingUtilities.convertPoint(content.getGlassPane(), e.getPoint(), content.getContentPane());
Point p = e.getPoint();
Component component = SwingUtilities.getDeepestComponentAt(content.getContentPane(), p.x, p.y);
System.out.println(component.toString());
Point p2 = component.getLocation();
MouseEvent event = new MouseEvent(component, e.getID(), e.getWhen(), e.getModifiers(), p2.x, p2.y, e.getClickCount(), e.isPopupTrigger());
//following lines have the same effects
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
//component.dispatchEvent(event);
}
Thanks for your help/suggestions
Okay, here's some more Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import resize.ResizablePanel;
public class ExampleProblem extends JFrame {
public ExampleProblem () {
JPanel glassPane = new JPanel();
glassPane.setOpaque(false);
glassPane.addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent e) {
resendEvent(e);
}
#Override
public void mouseReleased(MouseEvent e) {
resendEvent(e);
}
});
this.setGlassPane(glassPane);
glassPane.setVisible(true);
JButton b = new JButton("Test");
b.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("Button clicked");
}});
JPanel p = new JPanel();
p.add(b);
setContentPane(p);
pack();
setVisible(true);
}
private void resendEvent(MouseEvent e) {//Point p = SwingUtilities.convertPoint(content.getGlassPane(), e.getPoint(), content.getContentPane());
Point p = e.getPoint();
Component component = SwingUtilities.getDeepestComponentAt(this.getContentPane(), p.x, p.y);
System.out.println(component.toString());
Point p2 = component.getLocation();
MouseEvent event = new MouseEvent(component, e.getID(), e.getWhen(), e.getModifiers(), p2.x, p2.y, e.getClickCount(), e.isPopupTrigger());
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
}
public static void main(String[] args) {
new ExampleProblem();
}
}
Hope, the problem is a bit clearer now.
Is it possible, that I shouldn't have used setContentPane()? But we had to overwrite the JContentPane for resizing the components on it...
You have to determine the component point from your coordinate. Use this instead of p2 to to create the event:
Point p2 = SwingUtilities.convertPoint(this.getGlassPane(), p, component);
You might be able to use the Component Resizer. It would need to be added to all components in advance.
Or maybe you could add the listener when you select the component and then remove the listener when you deselect the component.
The code you posted is of little help when guessing what your actual program is doing. When you have problems with your code you need to post a SSCCE.

Categories