I'm doing a Java project which includes little bit of graphical stuffs. I want to display set of BufferedImages under Accordion menu kind of thing. that means when I click on one Accordion menu root item it should display set of images under that name and when clicking on another root menu item it should show another set of images. How could I implement this with Java?. Is there any way to add JPanel as Accordion menu leaf item? If anyone can provide sample code it is really appreciable.
Couldn't resist some fun: turns out that it's possible to tweak a JXTaskPaneContainer (in SwingX) a bit to behave similar to an accordion. All that's needed it to force at most one of the contained JXTaskPaneContainers to be expanded. Something like the code snippet:
JXTaskPaneContainer container = new JXTaskPaneContainer() {
private JXTaskPane current;
private PropertyChangeListener expansionListener;
/**
* #inherited <p>
*/
#Override
protected void addImpl(Component comp, Object constraints, int index) {
super.addImpl(comp, constraints, index);
if (comp instanceof JXTaskPane) {
grabExpansionControl((JXTaskPane) comp);
}
}
private void grabExpansionControl(JXTaskPane comp) {
if (current != null) {
comp.setCollapsed(true);
} else {
current = comp;
comp.setCollapsed(false);
}
comp.addPropertyChangeListener("collapsed",
getExpansionListener());
}
private void updateCurrentTaskPane(JXTaskPane source) {
if (source != current) {
if (!source.isCollapsed()) {
if (current != null) {
current.setCollapsed(true);
}
current = source;
}
}
}
private PropertyChangeListener createExpansionListener() {
PropertyChangeListener l = new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
// TODO Auto-generated method stub
updateCurrentTaskPane((JXTaskPane) evt.getSource());
}
};
return l;
}
private PropertyChangeListener getExpansionListener() {
if (expansionListener == null) {
expansionListener = createExpansionListener();
}
return expansionListener;
}
};
((VerticalLayout) container.getLayout()).setGap(0);
Well a little bit of googling and I found this link .
It may be helpful for you -
http://code.google.com/p/martin-personal-project/downloads/detail?name=SwingAccordionMenu.zip&can=2&q=
You will get a ZIP file , unzip and run the SwingAccordionMenu.jar, you will get accordion as output like -
Related
I need help implementing my own traversal policy.
My goal was to be able to traverse with tab some of the components in a panel, not all of them.
I was able to research the FocusTraversalPolicy class and figure out a little how this works. The code below shows how far I got. But I seem to have hit a wall.
This code will allow me to traverse from one component to another, but there are in my Container smaller jpanels with jtextfields in them. For some reason, I am not able to traverse to these using tab, even though I added the jpanels into my policy.
I am aware that I can just access the textfields inside these jpanels and add them to my policy. However, since these smaller jpanels are sort of dynamic and can add extra components inside of them, I am looking more for something that will allow me to pass from the Parent container traversal cycle to the smaller one.
I could be wrong, but I believe I should add something to the getComponentAfter(...) and the getComponentBefore(...) methods. As you can see, I commented out some of the things I was trying. I would appreciate any help you can give me. I attached a picture of my panel so you can see what I mean.
public class TabFocusAdapter extends FocusTraversalPolicy implements FocusListener, MouseListener {
private ArrayList<Component> comps = new ArrayList<Component>();
private int focus, def;
private boolean mouse_focus = false;
public TabFocusAdapter(int f) {
focus = def = f;
}
#Override
/***Returns the component after the current one
* if current one is the last in the cycle, it will return the first
* it will skip all disabled components */
public Component getComponentAfter(Container aContainer, Component aComponent) {
//if(((Container) aComponent).getFocusTraversalPolicy()!=null)
//if(aComponent)
//return ((Container)aComponent).getFocusTraversalPolicy().getFirstComponent((Container) aComponent);
focus++;
if(focus == comps.size()) focus = 0;
Component comp = comps.get(focus);
while(!comp.isEnabled() || !comp.isShowing() || !comp.isVisible()) {
focus++;
if(focus == comps.size()) focus = 0;
comp = comps.get(focus);
}
return comps.get(focus);
}
#Override
/**Returns the component before the current one
* if current one is the first in the cycle, it will return the last
* it will skip all disabled components */
public Component getComponentBefore(Container aContainer, Component aComponent) {
focus--;
if(focus == -1) focus = comps.size()-1;
Component comp = comps.get(focus);
while(!comp.isEnabled() || !comp.isShowing() || !comp.isVisible()) {
focus--;
if(focus == -1) focus = comps.size()-1;
comp = comps.get(focus);
}
return comps.get(focus);
}
#Override
public Component getFirstComponent(Container aContainer) {
return comps.get(0);
}
#Override
public Component getLastComponent(Container aContainer) {
return comps.get(comps.size() - 1);
}
#Override
/**Returns the starting component */
public Component getDefaultComponent(Container aContainer) {
return comps.get(def);
}
public void addComp(Component comp) {
comps.add(comp);
comp.addMouseListener(this);
comp.addFocusListener(this);
}
#Override
public void focusGained(FocusEvent e) {
Component comp = e.getComponent();
if(!mouse_focus && comp instanceof JTextComponent)
((JTextComponent)comp).selectAll();
}
#Override
public void mousePressed(MouseEvent e) {
mouse_focus = true;
focus = comps.indexOf(e.getComponent());
}
#Override
public void mouseReleased(MouseEvent e) {
mouse_focus = false;
}
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void focusLost(FocusEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
}
I solved my problem by including a series of checks into the getComponentAfter(...) and getComponentBefore(...) methods. I am including my code below.
Basically, to determine whether to move to a lower cycle, it asks whether the next component is a Focus Cycle Root.
When concluding a cycle, to determine whether to move to an upper cycle, it asks whether the parent of the container is a Focus Traversal Policy Provider.
I got the general idea for this solution by looking at how these methods where implemented by the default traversal policies of my JFrame.
'''
public Component getComponentAfter(Container aContainer, Component aComponent) {
Component comp;
do{
focus++;
if(focus == comps.size()) {
focus = 0;
ancestor = aContainer;
do ancestor = ancestor.getParent();
while(ancestor!=null && !ancestor.isFocusTraversalPolicyProvider());
if(ancestor != null && ancestor.isFocusTraversalPolicyProvider())
return (ancestor
.getFocusTraversalPolicy()
.getComponentAfter(ancestor, aContainer));
}
comp = comps.get(focus);
} while(!comp.isEnabled() || !comp.isShowing() || !comp.isVisible());
if(comp instanceof Container && ((Container)comp).isFocusCycleRoot()) {
return ((Container)comp)
.getFocusTraversalPolicy()
.getDefaultComponent((Container) comp);
}
return comp;
}
'''
I would like to make my own method that controles when a component is 'isSelected'.
I have a JList containing multiple JPanel. The constructing class of the JPanel extends ListCellRenderer<>.
To show that one of the JList-component (the JPanels) is selected i use;
#Override
public Component getListCellRendererComponent(..., boolean isSelected, ...) {
if(isSelected){
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
return this;
}
I would like a method that keeps a selected item 'selected' eventhough I choose to select another. I understand this can be done by holding down CTRL, but .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); does not quite do the trick. I would rather like to select multiple by clicking on them, and deselect by clicking on them.
For this i have worked with the ListSelectionMode, but i cant find a way.
When done the above I would like to implement a method that only selects a component in the list when clicked in a certain area (instead of the whole component which is preset). I have made this method, which returns true if the correct area is clicked, else false. But since I cant figure out how to override the mouseevent that makes the components 'isSelected' this has been tricky.
Here is the code for the method I would like to override the 'isSelected' method;
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent evt) {
if(ActionHandler.mouseClickedPrebuild(evt.getPoint())){
//This code runs if that special place is clicked!
//So now the component should be 'isSelected' or
//deselected if it already was 'isSelected'.
}
}
});
This code is in the constructor of my JList
And the mouseClickedPrebuild method;
public static boolean mouseClickedPrebuild(Point point) {
int index = theJList.locationToIndex(point);
Rectangle bounds = theJList.getCellBounds(index,index);
Point p = bounds.getLocation();
return ( ... long list of greater than & less than ...);
//This gives the certain area which is accepted to return true
I solved the issue!
So I get my view showing by running this line;
// UI Class JScrollPane Custom JList
UIConstructor.listview.setViewportView(new ListView( -insert ArrayList here- ));
Here is my ListView. The custom DefaultListSelectionModel I used to solve my problem was posted by #FuryComptuers right here;
JList - deselect when clicking an already selected item
I had to make a few changes to the code, since the two methods in the selectionModel will run before my mouseevent. I saved the variabels staticly, so instead of running the code in setSelectionInterval I did it inside my mousePressed.
I then could add the boolean isSelected which returns true, if a curtain area within a specific list element is clicked.
public class ListViewd extends JList {
static boolean isSelected;
static Point point;
static boolean gS = false;
static int in0;
static int in1;
#Override
public Dimension getPreferredScrollableViewportSize() {
Dimension size = super.getPreferredScrollableViewportSize();
size.setSize(new Dimension(0,0));
return size;
}
public ListView(ArrayList<System> items) {
DefaultListModel<System> list = new DefaultListModel<System>();
for (System item : items) {
list.addElement(item);
}
this.setSelectionModel(new DefaultListSelectionModel() {
boolean gestureStarted = false;
#Override
public void setSelectionInterval(int index0, int index1) {
gS = gestureStarted;
in0 = index0;
in1 = index1;
gestureStarted = true;
}
#Override
public void setValueIsAdjusting(boolean isAdjusting) {
if (!isAdjusting) {
gestureStarted = false;
}
}
});
ListSelectionModel selectionModel = this.getSelectionModel();
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
point = e.getPoint();
isSelected = ActionHandler.mouseClickedPrebuild(point);
if(!gS && isSelected){
if (isSelectedIndex(in0)) {
selectionModel.removeSelectionInterval(in0, in1);
} else {
selectionModel.addSelectionInterval(in0, in1);
}
}
}
});
setModel(list);
setCellRenderer(new ListModelPrebuild());
}
There is a good thread on how to correctly hook up a right-click menu to a Jface TreeViewer depending on the selected item.
I would like to show the right click menu depending on: if the right-click was on a node or into "empty space". The problem is that TreeViewer does not automatically clear the selection if you click into empty space. Is there any clean way how to achieve this?
My current approach would be to simply hook up a MouseListener to the tree with the following mouseDown method:
#Override
public void mouseDown(MouseEvent e) {
TreeItem item = treeViewer.getTree().getItem(new Point(e.x, e.y));
if (item == null) {
treeViewer.getTree().deselectAll();
}
}
This seems to work quite well. What do you think of this?
Ok, I found a dirty workaround. So if you really want to do it, here is a possible solution:
final Tree tree = viewer.getTree();
final Menu menu = new Menu(tree);
tree.setMenu(menu);
menu.addMenuListener(new MenuAdapter()
{
#Override
public void menuShown(MenuEvent e)
{
Point point = tree.toControl(Display.getDefault().getCursorLocation());
boolean found = false;
for (TreeItem item : tree.getItems())
{
for (int i = 0; i < tree.getColumnCount(); i++)
if (item.getBounds(i).contains(point))
found = true;
}
System.out.println(found);
}
});
How to add popup menu to your SWT/JFace TreeViewer
Hi, in your applications main class (that extends ApplicationWindow) in protected Control createContents(Composite parent) method you should add code like this:
//Author: Darius Kucinskas (c) 2008-2009
//Email: d[dot]kucinskas[eta]gmail[dot]com
//Blog: http://blog-of-darius.blogspot.com/
//License: GPL
// Create the popup menu
MenuManager menuMgr = new MenuManager();
Menu menu = menuMgr.createContextMenu(mTreeViewer.getControl());
menuMgr.addMenuListener(new IMenuListener() {
#Override
public void menuAboutToShow(IMenuManager manager) {
if(mTreeViewer.getSelection().isEmpty()) {
return;
}
if(mTreeViewer.getSelection() instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection)mTreeViewer.getSelection();
DatabaseModelObject object = (DatabaseModelObject)selection.getFirstElement();
if (object.getType() == DATABASE_OBJECT_TYPE.TABLE){
manager.add(new ShowTableDataAction(SWTApp.this));
}
}
}
});
menuMgr.setRemoveAllWhenShown(true);
mTreeViewer.getControl().setMenu(menu);
DatabaseModelObject - is class from my problem domain (specific to my program). mTreeViewer - is object of TreeViewer class (JFace). Thanks, have a nice day!
The default context menu of SWT Text in windows has several options that we did not want. As the default context menu is provided by the operating system and cannot be modified, I created a custom context menu with only basic Text operations such as delete, cut, copy and paste for the Text boxes.
The problem now is that when I copy text from another application and try pasting into the TextBox, the paste doesn't seem to work. But it works when we copy/cut text within the application itself.
Here is the code for copy and paste.
Paste Action:
private class PasteActionHandler extends Action {
/** Creates a new instance. */
private PasteActionHandler() {
...
setEnabled(false);
}
#Override
public void runWithEvent(Event event) {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
activeTextControl.paste();
updateActionsEnableState();
return;
}
}
/**
* Updates the state of the Paste Action.
*/
public void updateEnabledState() {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
boolean canPaste = false;
if (activeTextControl.getEditable()) {
Clipboard clipboard = new Clipboard(activeTextControl.getDisplay());
TransferData[] td = clipboard.getAvailableTypes();
for (int i = 0; i < td.length; ++i) {
if (TextTransfer.getInstance().isSupportedType(td[i])) {
canPaste = true;
break;
}
}
clipboard.dispose();
}
setEnabled(canPaste);
return;
}
setEnabled(false);
}
}
Copy Action:
private class CopyActionHandler extends Action {
private CopyActionHandler() {
...
setEnabled(false);
}
#Override
public void runWithEvent(Event event) {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
activeTextControl.copy();
updateActionsEnableState();
return;
}
}
/**
* Updates the state of the {#link Action}.
*/
public void updateEnabledState() {
if (activeTextControl != null && !activeTextControl.isDisposed()) {
setEnabled(activeTextControl.getSelectionCount() > 0);
return;
}
setEnabled(false);
}
}
As you could see, I call the Text control's copy and paste functions to do the operations.
Also is there a way in SWT to get the system clipboard?
To copy something in the clipboard from SWT i use the code:
String textData = textControl.getText();
if (textData.length() > 0) {
org.eclipse.swt.dnd.Clipboard cb = new org.eclipse.swt.dnd.Clipboard(display);
org.eclipse.swt.dnd.TextTransfer textTransfer = org.eclipse.swt.dnd.TextTransfer.getInstance();
cb.setContents(new Object[]{textData}, new Transfer[]{textTransfer});
}
you can try that instead of activeTextControl.copy() function and see if it works
Now that I am able to set the content of my second wizard's page depending on the first page selection, I am looking for a way to give the focus to my 2nd page's content when the user clicks the next button on the first page.
By default, when the user click the next button, the focus is given to the button composite (next, back or finish button depending on the wizard configuration)
The only way I found to give focus to my page's content is the following one:
public class FilterWizardDialog extends WizardDialog {
public FilterWizardDialog(Shell parentShell, IWizard newWizard) {
super(parentShell, newWizard);
}
#Override
protected void nextPressed() {
super.nextPressed();
getContents().setFocus();
}
}
To me it's a little bit "boring and heavy" to have to override the WizardDialog class in order to implement this behavior. More over, the WizardDialog javadoc says:
Clients may subclass WizardDialog, although this is rarely required.
What do you think about this solution ? Is there any easier and cleaner solution to do that job ?
This thread suggests:
In your wizard page, use the inherited setVisible() method that is called automatically before your page is shown :
public void setVisible(boolean visible) {
super.setVisible(visible);
// Set the initial field focus
if (visible) {
field.postSetFocusOnDialogField(getShell().getDisplay());
}
}
The postSetFocusOnDialogField method contains :
/**
* Posts <code>setFocus</code> to the display event queue.
*/
public void postSetFocusOnDialogField(Display display) {
if (display != null) {
display.asyncExec(
new Runnable() {
public void run() {
setFocus();
}
}
);
}
}
VonC's answer works great, I personally found it to be a little easier to work with like this though:
#Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
Control control = getControl();
if (!control.setFocus()) {
postSetFocus(control);
}
}
}
private void postSetFocus(final Control control) {
Display display = control.getDisplay();
if (display != null) {
display.asyncExec(new Runnable() {
#Override
public void run() {
control.setFocus();
}
});
}
}