Java Swing - Display table in sub menu - swing

I have a menu that displays say
Item1
Item2
Item3
etc. Clicking on Item1 should display me a Table with 2 columns.
I tried something below with displaying just a label. But the label gets displayed somewhere in the screen where as I am expecting it to be a submenu under menuitem1.
JMenu mainMenu = new JMenu("MainMenuHeader");
JMenu menuItem1 = new JMenu(new SomeClassExtendingAbstractAction("menuItem1"));
public class SomeClassExtendingAbstractAction extends AbstractAction {
public SomeClassExtendingAbstractAction(String displayText) {
super(displayText);
}
public void actionPerformed(ActionEvent event) {
try {
SubMenuDialog.showDialog(parent);
} catch (Throwable e) {
}
}
}
public class SubMenuDialog extends JDialog {
public SubMenuDialog(JFrame parent) {
super();
initialize();
}
private void initialize() {
JLabel label = new JLabel();
label.setText("This is test submenu");
getContentPane().add(label);
}
public static void showDialog(JFrame parent) {
SubMenuDialog subMenuDialog = new SubMenuDialog(parent);
subMenuDialog.pack();
subMenuDialog.setVisible(true);
}
}

If I understand correctly, what you want to do is to show arbitrary component in a submenu popup. You obviously cannot use JDialog as it would give you a, you know, JDialog.
Your SubMenuDialog#showDialog can create a JPopupMenu, add any component to it (for example JScrollPane containing a table, or JPanel with labels), and show it where a normal submenu would be.
However it's not a good idea in general to show complicated things in a popup, since it's too easy to lose the popup, plus you may get focus problems with components inside the popup.
I'd suggest you consult a UI designer for the best UI representation of the functionality you want to implement.

Related

Making JavaFX Alerts/Dialogs Modal within Swing Application

So once again we are in the process of converting our existing Java application that was using entirely Swing to using JavaFX. However, the application will not be using JavaFX entirely. This seems to be causing some issues with Alerts/Dialogs and modality. We are currently using Java 8u40.
The main application is basically in a JFrame that has a Menu. The main content pane is JDesktopPane and clicking a MenuItem opens new JInternalFrames within the DeskopPane. Screens we are converting to JavaFX are basically JFXPanels within a JInternalFrame at the moment. Any Alerts/Dialogs that are opened from the JFXPanels are modal to the panel itself, but not to the JInternalFrame, DeskopPane, Menu, etc.
I read in the DialogPane documentation that they are planning to introduce some lightweight dialogs and even possibly InternalFrames in future releases of JavaFX, so maybe we'll just have to wait it out a little longer for this functionality. But, ideally when opening a new Alert/Dialog it would be modal to the entire Application.
EDIT:
Currently doing the following for modal dialogs:
((Stage)getDialogPane().getScene().getWindow()).setAlwaysOnTop(true);
This makes the dialog always appear on top, however the dialog also remains on top of other applications even if our main application is minimized. It also does not block input to any Swing components in the frame.
You can use the following work-around which creates an invisible JDialog when the Alert is shown and disposes the JDialog when the Alert is closed. This approach extends the modality to the whole application, including the Swing part.
// create Alert
Alert alert = new Alert(AlertType.INFORMATION, "Hello");
// create invisible JDialog and "show" it
JDialog dialog = new JDialog();
dialog.setModal(true);
dialog.setUndecorated(true);
dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
SwingUtilities.invokeLater(() -> dialog.setVisible(true));
// show Alert
alert.showAndWait();
// close JDialog after Alert is closed
dialog.dispose();
I don't think i understand your question completely. But here is my guess - You are trying to make an alert window from some JFXPanel that will be modal (i.e. user will not be able to click in your application until she closes that alert window) to your entire application which is written partially using swing components.
If your application would be written in purely JavaFX then you would do something like (Assuming you have created a button somewhere in your JFXPanel)
button.setOnAction(evt -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.initModality(Modality.APPLICATION_MODAL);
// This will not work in your code
alert.initOwner(button.getScene().getWindow());
alert.show();
});
but since initOwner requires a javafx.stage.window object passing a swing component won't work in your code. As of Java 8u40 i don't think there is a right way(i.e. not hacks) to set ownership of Alert objects to swing component. Not surprisingly such questions has already been asked here and not answered as of writing this.
For your requirements you can use JOptionPane.showMessageDialog method and its look alike as workaround.
button.setOnAction(evt -> {
JOptionPane.showMessageDialog(desktopPane,"My message");
});
These dialog boxes are modal by default so no work is necessary. You can call these from any event handler methods of JavaFX components.
I've done a little workaround with a small interface which is implemented in my JavaFXFrame:
public interface DialogParent {
void setOnFocusGained(EventHandler<FocusEvent> focusHandler);
void setOnCloseRequest(EventHandler<WindowEvent> closeHandler);
}
And my JavaFXFrame implementation
public class JavaFXFrame implements DialogParent {
private JFrame frame;
private EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler;
private EventHandler<javafx.stage.WindowEvent> windowClosingHandler;
public void JavaFXFrame() {
final JFXPanel fxPanel = new JFXPanel();
frame = new JFrame();
frame.add(fxPanel);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
tryClosing(this);
}
});
frame.addWindowFocusListener(new WindowAdapter() {
#Override
public void windowGainedFocus(WindowEvent e) {
if (focusGainedHandler != null) {
focusGainedHandler.handle(new FocusEvent());
}
}
});
}
public void setVisible(boolean visible) {
frame.setVisible(visible);
}
private void tryClosing(WindowListener listener) {
javafx.stage.WindowEvent windowEvent = new javafx.stage.WindowEvent(null, javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST);
if (windowClosingHandler != null) {
windowClosingHandler.handle(windowEvent);
}
if (!windowEvent.isConsumed()) {
frame.setVisible(false);
}
}
#Override
public void setOnFocusGained(EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler) {
this.focusGainedHandler = focusGainedHandler;
}
#Override
public void setOnCloseRequest(EventHandler<javafx.stage.WindowEvent> windowClosingHandler) {
this.windowClosingHandler = windowClosingHandler;
}
}
And showing an Alert:
public static void showAlert(Alert alert) {
DialogPane dialogPane = alert.getDialogPane();
final Stage stage = new Stage();
stage.setScene(dialogPane.getScene());
List<ButtonType> buttonTypes = dialogPane.getButtonTypes();
for (ButtonType buttonType : buttonTypes) {
ButtonBase button = (ButtonBase) dialogPane.lookupButton(buttonType);
button.setOnAction(evt -> {
dialogPane.setUserData(buttonType);
stage.close();
});
}
dialogParent.setOnFocusGained(event -> {
stage.toFront();
});
dialogParent.setOnCloseRequest(Event::consume);
stage.setOnCloseRequest(event -> {
dialogParent.setOnFocusGained(null);
dialogParent.setOnCloseRequest(null);
});
stage.show();
}
Hope this will help you

Listener on MenuBar in Vaadin

I want to add a ClickListener to an Item of a MenuBar in Vaadin.
I know about the normal situation, which i got working:
MenuBar menubar = new MenuBar();
menubar.addItem("Item", new MenuBar.Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
//Do sth. when item is clicked
}
});
In my application, I'm working with MVP, so the code which should run, is in an other class than the code which is defining the menubar.
Is there a way to add a listener to a specific item in the menubar ?
When you add an item to your MenuBar the function addItem(String,Command) actually returns a MenuItem which can be used later. You can do this :
MenuItem select = menuBar.addItem("Select", null);
And in another context you can add a listener on that MenuItem like this:
select.setCommand(new Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
System.out.println("You clicked on "+selectedItem.getText());
}
});

Swing tooltip resizable

I've tried to implement a resizeable tooltip but have some problems with this.
When the tooltip is shown, the text updates on change in the model (implemented with property change listener). What I need now is, that the tooltip changes its size as well depending on the text.
Tried revalidate, doLayout and repaint but with no effect. The tooltip doesn't change its size.
Only moving the mouse gives me a correct sizing for the first text which is displayed in the tooltip.
Can anybody help?
Here are some code snippets: first of all my tolltip class:
public class ResizeableToolTip extends JToolTip {
public ResizeableToolTip(final JComponent component) {
super(component);
initComponents();
}
#Override
protected void initGUI() {
super.initGUI();
setLayout(new BorderLayout());
}
/**
* Component initialization goes here...
*/
private void initComponents() {
setTipText(getComponent().getToolTipText());
setPreferredSize(calculateOptimalSize());
}
private abstract Dimension calculateOptimalSize();
#Override
public void setTipText(String tipText) {
super.setTipText(tipText);
setPreferredSize(calculateOptimalSize());
revalidate();
}
}
Then I have a button which is using this implementation:
public class MyButton extends JButton implements PropertyChangeListener {
//...
private ResizeableToolTip tooltip;
//...
private initComponents() {
//...
tooltip = new ResizeableToolTip(this);
//...
}
//...
public void propertyChange(final PropertyChangeEvent pcevt) {
//...
if (MyButtonModel.TOOLTIPTEXT_PROPERTY.equals(pcevt.getPropertyName()) {
tooltip.setTiptext((String) pcevt.getNewValue());
tooltip.repaint();
}
//...
}
//...
}
The result should be a tooltip which is displayed over the button where the text is changing when s.th. changes in the data model. The text changes are working but the size of the box of the tooltip stays on the wrong size.
As far as i can tell there is not way to resize it besides moving the mouse. However the component should have one mouse mouse motion listener so all you have to do is call mouseMoved on that and it will think the mouse has been moved and will resize the tooltip.
//comp will be whatever component your tooltip is on
if(comp.getMouseMotionListeners().length > 0)comp.getMouseMotionListeners()[0].mouseMoved(new MouseEvent(inst, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(), 0, MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y, 0, false));
Just call that after you set the tooltip and it should resize.

I wrote a program using Drag and Drop in java, I need few updation in this. Can anyone help me please?

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class scjp extends TransferHandler
{
JTextField txtField;
JRadioButton lbl=new JRadioButton("Hello");
public static void main(String[] args)
{
scjp sdd = new scjp();
transfer th=new transfer();
}
public scjp()
{
MouseListener ml = new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
JComponent jc = (JComponent)e.getSource();
TransferHandler th = jc.getTransferHandler();
th.exportAsDrag(jc, e, TransferHandler.COPY);
}
};
MouseMotionListener m2=new MouseAdapter()
{
public void mouseDragged(MouseEvent e)
{
}
};
JFrame frame = new JFrame("SCJP");
txtField = new JTextField(20);
lbl.setTransferHandler(new TransferHandler("text"));
lbl.addMouseListener(ml);
lbl.addMouseMotionListener(m2);
JPanel panel = new JPanel();
panel.add(txtField);
frame.add(lbl, BorderLayout.CENTER);
frame.add(panel, BorderLayout.NORTH);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EX…
frame.setResizable(false);
}
}
here i m dragging a radio and dropping that into a textBox, when i m dragging the radio button, my mouse pointer looks like (a rectangle and plus sign below the arrow).
What i need to do:
when i pick/drag the radio that time instead of that rectangle and plus sign, i want that string which is of radio??
i mean to say the radio button string/text i want as with my mouse cursor upto i drop that component/radio in text box..?
please help me to figure out this problem as soon as possible, please.
First look here - this explains how to change the cursor while performing drag n drop.
Once you understand the concept, you will have to code a method that creates an in-memory image of text from the radio button in question. That image can be used in populating the cursor.
Pseudo code:
img = //in-memory image created by writing text of radio button to graphics.
Cursor curCircle = Toolkit.getDefaultToolkit().createCustomCursor(img,new Point(5,5),"some text");
Set the new cursor in dragEnter - and then take care of dragExit to restore original cursor.

NotSerializableException for ToolkitImage when serializing a model in Swing

I have Swing application which manipulate shapes. In my toolbar I have a zoom function that the user activate by clicking on a button, then the cursor of the mouse changes to a magnifier which is an image.
My problem is actually the cursor, for some raisons, when I set the cursor on the panel displaying the shapes, I can't save my model and I get the java.io.NotSerializableException: sun.awt.image.ToolkitImage exception.
My model
public class Document implements IDocObservable,Serializable{
...
public void updateCursor() {
Iterator<IDocObserver> iter = docObservers.iterator();
while (iter.hasNext()) {
iter.next().docCursorChanged();
}
}
...
}
The action
public class ZoomInAction extends AbstractAction {
public void actionPerformed(ActionEvent arg0) {
...
Application.getInstance().getActiveDocument().updateCursor();
}
}
The display Panel (note : if I comment the setCursor(..) line, I'am able to save )
public class Window extends JPanel implements IDocObserver{
...
public void paint(Graphics g){
//drawing the differents shapes
}
#Override
public void docCursorChanged() {
setCursor(Utile.getZoomInCursor();
}
}
}
The class that provide the cursor
public class Utile {
private static Image zoomIn = toolkit.getImage(Utile.class.getResource("/images/zoomin_mouse.png"));
...
public static Cursor getZoomInCursor() {
return toolkit.createCustomCursor(zoomIn, hotSpot, "");
}
}
The writing of the object is a standard Java methode with outStream.writeObject(doc);
thanks
You aren't just serializing a model, you are serializing a list of IDocObservers, which includes Window extends JPanel implements IDocObserver. IOW you are serializing a JPanel. Don't do that: see the warning at the top of the Javadoc. You don't need to save the observers along with the observable, surely: can't you make that list transient?