moving / scrolling up and down on three JTable simultanously. - java

I have three different jtable on three diffenernt jscrollpane - one next to the other.
I successfuly written some code that makes them all scroll together when I scroll the mouse wheel.
I inherrited JScrollpane and overriden its processMouseWheelEvent methos as follows:
public void processMouseWheelEvent(MouseWheelEvent e) {
...
if (e.getSource() == this) {
for (BTSJScrollPane other : effected) {
other.processMouseWheelEvent(e);
}
}
}
I have canelled the pageup pagedown using
final InputMap inputMap =
comp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
inputMap.put(KeyStroke.getKeyStroke("PAGE_DOWN"), EMPTY);
inputMap.put(KeyStroke.getKeyStroke("PAGE_UP"), EMPTY);
comp.getActionMap().put(EMPTY, emptyAction);
But,
my only problem now is that when the user clicks up and down, they dont go together but rather scroll indipently.
Any suggestions ?
So far I wrote in my scrollpane something like
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
#Override public boolean dispatchKeyEvent(KeyEvent e) {
if (thisIsThesourceTable) {
if (e.getKeyCode() == 38 || e.getKeyCode() == 40) {
}
}
return false;
}
});
But :
1. is there a better way?
2. maybe I should do it somehow in the actionMap?
3. how do I pass the key up/down event to the other scrollpane?
4. can I know if I am near the end of the viewing part in the scroll pane? is it needed

1, 2, & 3: You should use listeners on the scrollbars so it works with mouse, keyboard, and scrollbar interaction. That way you won't need key or mouse listeners. Here is one way:
scroll1.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
scroll2.getVerticalScrollBar().setValue(e.getValue());
}
});
4: Look at JScrollPane's getVerticalScrollBar().getMaximumSize() and getModel() to find out if you're near the end.

Related

JFrame Selecting Multiple Objects

I would like to know if the multiple selections function used in list, will be workable too in the object?
The example I found was working on the list as provided from the link.
https://stackoverflow.com/questions/25691623/jlist-listselectionlistener-multiple-interval-selection-that-waits-for-cntrl-or
The current project I'm working on is to draw different shapes which is an object. After done drawing, I shall be able to select more than 1 object by holding the SHIFT key.
How can I do that?
you can not re-use the List-Selection-Model in a simple way - i really recommend to use your own implemention instead.
To do so you must add a KeyListener and a MouseListener on your Panel in order to check for Shift pressed or not.
private boolean isShiftDown = false;
KeyAdapter ka = new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(e.getKeyCode() == KeyEvent.VK_SHIFT){
isShiftDown=false;
}
}
#Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
if(e.getKeyCode() == KeyEvent.VK_SHIFT){
isShiftDown=true;
}
}
};
use your own selection 'model' which will be a simple list (java.util.List)
private List<Shape> selectionList = new ArrayList();
MouseAdapter ma = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
Shape shape = findShapeAt(e.getX(), e.getY() ); //i guessed you had a methode like that
if (shape != null){
//check is your shift key is down
if (isShiftDown){
//add or remove on click
if (selectionList.contains(shape) ){
selectionList.remove(shape);
}else{
selectionList.add(shape);
}
}else{
//if shift is NOT down, clear the list before adding
selectionList.clear();
selectionList.add(shape);
}
}
//show the selection in your gui();
updateSelection(); //that's your part - draw a nice border around all Shapes from the selectionList
}
};
don't forget to add both keyListener(KeyAdapter) and MouseListener(MouseAdapter) to your panel...
NOTE
i would really use the ctrl-key (KeyEvent.VK_CONTROL) instead of the shift-key to add/remove shapes by single-mouse-klick...

JPopupMenu on JTable -> Get the cell the menu was created on

I have a situation where I have a popup menu created when a JTable is right clicked on. Standard way of creating the popup menu:
aJTable.setComponentPopupMenu(rightClickMenu);
Now afterwards in the action that gets registered, I am unable to find out which cell was right clicked on to get that popup menu to appear.
rightClickMenuItem.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Work out what cell was right clicked to generate the menu
}
});
Any ideas on how you do this?
Astonishing fact: with a componentPopupMenu installed, a mouseListener never sees the mouseEvent that is the popupTrigger (reason is that showing the componentPopup is handled globally by a AWTEventListener installed by BasicLookAndFeel, and that listener consumes the event).
The only place which sees the mousePosition of that trigger is the getPopupLocation(MouseEvent), so the only reliable way to get hold of it (for doing location dependent config/actions) is #Mad's suggestion to override that method and store the value somewhere for later use.
The snippet below uses a clientProperty as storage location:
final JTable table = new JTable(new AncientSwingTeam()) {
#Override
public Point getPopupLocation(MouseEvent event) {
setPopupTriggerLocation(event);
return super.getPopupLocation(event);
}
protected void setPopupTriggerLocation(MouseEvent event) {
putClientProperty("popupTriggerLocation",
event != null ? event.getPoint() : null);
}
};
JPopupMenu popup = new JPopupMenu();
Action action = new AbstractAction("show trigger location") {
#Override
public void actionPerformed(ActionEvent e) {
JPopupMenu parent = (JPopupMenu) SwingUtilities.getAncestorOfClass(
JPopupMenu.class, (Component) e.getSource());
JTable invoker = (JTable) parent.getInvoker();
Point p = (Point) invoker.getClientProperty("popupTriggerLocation");
String output = p != null ? "row/col: "
+ invoker.rowAtPoint(p) + "/" + invoker.columnAtPoint(p) : null;
System.out.println(output);
}
};
popup.add(action);
popup.add("dummy2");
table.setComponentPopupMenu(popup);
#MadProgrammer's suggestion of getPopupLocation looked promising, but I couldn't work out how to get the information across between the table and the actionEvent...
I got around this by making sure that the row was selected when you rightclicked on it -> since the popup menu prevents the selection of the row, you can add in a mouse listener that makes sure the row gets selected no matter what click (left or right) is pressed.
aTable.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
int r = aTable.rowAtPoint(e.getPoint());
if (r >= 0 && r < clt.getRowCount()) {
aTable.setRowSelectionInterval(r, r);
} else {
aTable.clearSelection();
}
}
});
This means that in the rightClickMenuItem's action listener, you can grab the table's selected cell / row
rightClickMenuItem.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
aTable.get details about the selected one....
}
});
Too easy! Thanks everyone for the help.
JTable has methods
int row = rowAtPoint(p);
int col = columnAtPoint(p);
So pass the MouseEvent's point and use the values
Add a MouseListener and store the last right click point somewhere.

Overriding the MouseWheelListener in Swing

I want to override the mouse wheel listener in Swing but only if they have the Control button pressed. The listener will be attached to a JPanel so that when they scroll the wheel it will scroll the JScrollPane and when they have the control button pressed and scroll the wheel it will zoom in. The default scroll of JScrollPane works (obviously) before I override it with my own listener. Here is my code:
mainPanel.addMouseWheelListener(new MouseWheelListener(){
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
int notches = e.getWheelRotation();
if (notches < 0) {
redrawOnZoom(true);
} else {
redrawOnZoom(false);
}
}
}
});
Is there a way of saying something like "If mouse is scrolled on its own then do default JScrollPane scrolling behaviour but If Ctrl is pressed then zoom"?
you can dispatch the event to its parent if you don't want to handle it:
final MouseWheelListener wheel = new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
// handle some events here and dispatch others
if (shouldHandleHere(e)) {
LOG.info("do-my-own-stuff");
} else {
LOG.info("dispatch-to-parent");
e.getComponent().getParent().dispatchEvent(e);
}
}
public boolean shouldHandleHere(MouseWheelEvent e) {
return (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0;
}
};
Hint:
Override the mouseWheelListener.
two functions : scroll() and other zoom.
Check for CTRL keyPress inside listener.
If pressed, call zoom() elsescroll()
refer tohow to write swing listener for guidence.

Java: JScrollPane disable scrolling when ctrl is pressed

I want to disable scrolling with the mousewheel in my JScrollPane while ctrl is pressed.
When you press ctrl and move the wheel you will zoom in/out AND also scroll the panel, which is not what I wanted.
Here's the working code:
scroller = new JScrollPane(view);
scroller.removeMouseWheelListener(scroller
.getMouseWheelListeners()[0]);
scroller.addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(final MouseWheelEvent e) {
if (e.isControlDown()) {
if (e.getWheelRotation() < 0) {
// Zoom +
} else {
// Zoom -
}
} else if (e.isShiftDown()) {
// Horizontal scrolling
Adjustable adj = getScroller().getHorizontalScrollBar();
int scroll = e.getUnitsToScroll() * adj.getBlockIncrement();
adj.setValue(adj.getValue() + scroll);
} else {
// Vertical scrolling
Adjustable adj = getScroller().getVerticalScrollBar();
int scroll = e.getUnitsToScroll() * adj.getBlockIncrement();
adj.setValue(adj.getValue() + scroll);
}
}
});
Edited my question and resolved it myself.
If you have any tweaks go ahead and tell me!
Take a look at Mouse Wheel Controller. You won't be able to use the exact code but you should be able to use the concept of the class.
The code replaces the default MouseWheelListener with a custom listener. Then it recreates the event with one different parameter in redispatches the event to the default listeners.
In your case you won't need to create a new event you will just need to prevent any event with a Control modifier from being redispatched to the default listeners and instead you invoke the code you posted in your question.
In order to temporarily disable scrolling you could manipulate the scrollbar's unit increment value and, respectively, restore it again.
Just add a key listener to the view port panel and react to Ctrl key pressed:
editorPane.addKeyListener(new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e) {
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0)
getVerticalScrollBar().setUnitIncrement(0);
else
getVerticalScrollBar().setUnitIncrement(15);
}
#Override
public void keyReleased(KeyEvent e) {
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0)
getVerticalScrollBar().setUnitIncrement(0);
else
getVerticalScrollBar().setUnitIncrement(15);
}
});

Setting caret position in JTextArea

I have a JTextArea. I have a function that selects some amount of text when some combination is called. It's done properly. The thing is, I want to move caret to the selection beginning when some text is selected and VK_LEFT is pressed. KeyListener is implemented properly, I tested it in other way. The thing is, that when I write following code:
#Override public void keyPressed( KeyEvent e) {
if(e.getKeyChar()==KeyEvent.VK_LEFT)
if(mainarea.getSelectedText()!=null)
mainarea.setCaretPosition(mainarea.getSelectionStart());
}
and add an instance of this listener to mainarea, select some text (using my function) and press left arrow key, the caret position is set to the end of selection... And I wont it to be in the beginning... What's the matter? :S
Here's a code snippet
Action moveToSelectionStart = new AbstractAction("moveCaret") {
#Override
public void actionPerformed(ActionEvent e) {
int selectionStart = textComponent.getSelectionStart();
int selectionEnd = textComponent.getSelectionEnd();
if (selectionStart != selectionEnd) {
textComponent.setCaretPosition(selectionEnd);
textComponent.moveCaretPosition(selectionStart);
}
}
public boolean isEnabled() {
return textComponent.getSelectedText() != null;
}
};
Object actionMapKey = "caret-to-start";
textComponent.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), actionMapKey);
textComponent.getActionMap().put(actionMapKey, moveToSelectionStart);
Note: it's not recommended to re-define typically installed keybindings like f.i. any of the arrow keys, users might get really annoyed ;-) Better look for some that's not already bound.

Categories

Resources