Vaadin GridLayout not updating correctly - java

I have a problem where Vaadin does not update the display of a GridLayout in time. The GridLayout is a component in a VerticalLayout, that I use to list all uploaded files. When I upload a file everything works fine on the server-side but the client does not see the change until he creates a new request to the server (by uploading another file or triggering some other event / rarely the update works fine though).
Here is the component that contains the problematic GridLayout:
public class ListedMultiFileUpload extends VerticalLayout {
private MultiFileUpload multiFileUpload;
private GridLayout fileList;
public ListedMultiFileUpload(UploadFinishedHandler uploadFinishedHandler, UploadStateWindow uploadStateWindow) {
multiFileUpload = new MultiFileUpload(uploadFinishedHandler, uploadStateWindow);
fileList = new GridLayout(2, 5);
fileList.setImmediate(true);
addComponents(multiFileUpload, fileList);
}
public SmartMultiUpload getSmartUpload() {
return multiFileUpload.getSmartUpload();
}
public void addFile(String fileName, final Runnable fileRemover) {
final Label label = new Label(fileName);
final Button button = new Button("X");
button.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
fileList.removeComponent(label);
fileList.removeComponent(button);
fileRemover.run();
}
});
fileList.addComponent(label);
fileList.addComponent(button);
markAsDirtyRecursive();
}
}
I already tried setting the GridLayout to immediate as well as marking the whole component as dirty but nothing seems to make a difference.
So basically am I doing something wrong here? Or if not, is there a "nice" way I could force the client to update its components?

As proposed by #Morfic I enabled the Server-Push addon in automatic mode and now the required updates to the client are made by that addon. Not sure how much I like that solution but it works.

Related

jMenuItem doesn't appear

I've just starting using Java Swing and I have a issue.
I tried to do a simple menuBar and a menuItem 'Exit', but before linking the button to the action the menuItem appeared, now that I've linked the button to a System.exit(0) action it disappeared. Help?
The code is the following:
in MainPanel (the autogenerated code from swing is excluded):
public void init() {
initComponents();
initActions();
setLocationRelativeTo(null);
pack();
setVisible(true);
}
private void initActions() {
this.menuItemExit.setAction(Application.getInstance().getPanelControl().getActionExit());
}
In PanelControl:
public class PanelControl {
private Action actionExit;
public Action getActionExit() {
return actionExit;
}
public class ActionExit extends AbstractAction{
public ActionExit(){
putValue(Action.NAME, "Exit");
putValue(Action.SHORT_DESCRIPTION, "Exit from the application");
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl e"));
putValue(Action.MNEMONIC_KEY, KeyEvent.VK_E);
}
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
In Application:
private void init() {
viewMainPanel = new MainPanel();
controlPanel = new ControlPanel();
viewMainPanel.init();
}
i think the problem is somewhere in here but i can't figure out where. any help?
(there's other code but i just put the more relevant part, also i translated the code from italian so i'm sorry if there are any problems or a few names dont match up)
private Action actionExit;
public Action getActionExit() {
return actionExit;
}
Your actionExit variable is null.
Nowhere in your code do you create an instance of your ActionExit class.
Somewhere you need:
actionExit = new ActionExit();
Your design seems a bit complicated, I have no idea why you have a panel just to create an instance of the ActionExit class.
I would suggest you just create the ActionExit instance in your main class and get rid of the PanelControl class.
Instead of using an IDE to generate confusing code you should consider learning how to write the code yourself so you can better structure your classes. Read the section from the Swing tutorial on How to Use Menus for a working example to get you started.
A menu item has to be added to a Native Java Swing component. You have to add it to a JFrame. You can't add a MenuItem to a Panel. The Parent 'root' container in any Java Swing application is 'native' and a JFrame. Everything else in that container is 'drawn' into the rectangle using the look and feel of your choosing.
Then you CREATE a MenuItem using your TAbstractAction item. That object CAN be used to create a JButton, JMenuItem or ToolBar button. Keeping a reference to your TAbstractAction in your code, you can enable/disable the object and it implements an 'observable' pattern where it will enable/disable ALL UI controls you used to build with it. I actually wrote a Java Swing framework for doing Java Applications. It used to be on the Sun Open Source web site. If you wish I can put it up on GitLab for you to play with. Java Swing is nice but JavaFX should be the long term goal for UI on a JVM.
In your JFrame object you need to do this:
_menuBar = new JMenuBar();
// add controls to the frame
setJMenuBar(_menuBar);
Then you need to add your 'exitMenuItem' to your _MenuBar control.
Cheers

Vaadin SliderPanel not displaying

I'm using the Vaadin add-on SliderPanel (https://vaadin.com/directory#!addon/sliderpanel) in my project and am having a very hard time making it go away and reappear on the correct view. When I load the application and log in, it correctly takes me to the correct class/page, 'Dashboard', with no SliderPanel. When I navigate to any other class/page which is supposed to re-display the SliderPanel, it does not appear as expected. In order for me to get it to show, I have to resize the window. Same thing happens when I resize the window then go back to the 'Dashboard' page...I have to resize the window and the SliderPanel tab goes away. How can I get the SliderPanel tab to update itself when changing views with the navigator?
In my UI I have #push() annotated above the main class.
#Push()
public class EvoltwebUI extends UI implements ClickListener {...}
Inside the class I have these annotations and servlet class:
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = EvoltwebUI.class, widgetset = "com.evolt.evoltweb.widgetset.EvoltwebWidgetset")
public static class Servlet extends VaadinServlet {
}
I've registered the views like this:
private void registerViews() {
navigator.addView("dashboard", DashboardViewImpl.class);
navigator.addView("groups", GroupsViewImpl.class);
navigator.addView("research", ResearchViewImpl.class);
navigator.addView("reporting", ReportsViewImpl.class);
navigator.addView("execution", AdhocExecView.class);
navigator.addView("tcreview", TestCaseReviewView.class);
navigator.addView("toolbox", ToolboxView.class);
}
The 'enter' method on each view/class looks like this:
#Override
public void enter(ViewChangeEvent event) {
presenter.onViewEnter(event.getParameters());
generateFields();
ProgressPanel.setViewName("Test Case Review - Please load a group from the Test Group Explorer Slider Panel on the left.");
evoltWebUI.getTreeViewSlider().defaultTab();
}
I've tried using these, but I am having the same type of issue to where it will not come back if setVisible is false. :
leftTreeViewSlider.setVisible(true);
leftTreeViewSlider.setVisible(false);
I've also tried extending SliderPanel to access the actual size of the tab to shrink it, but when setting it back to the normal size I have to resize the window to get it back.
import org.vaadin.sliderpanel.SliderPanel;
import org.vaadin.sliderpanel.SliderPanelBuilder;
import com.vaadin.ui.Component;
public class SliderPanelMod extends SliderPanel{
public SliderPanelMod(SliderPanelBuilder builder) {
super(builder);
}
public void resizeTab(int t) {
this.getState().tabSize = t;
}
public void defaultTab() {
resizeTab(40);
}
}
Does anyone have any ideas what would be causing this?

GXT FramedPanel Drag for header

I want include Grid in FramedPanel and using gxt dnd.
But if I add FramedPanel in DragSource:
DragSource source = new DragSource(framedPanel) {
#Override
protected void onDragStart(DndDragStartEvent event) {
super.onDragStart(event);
event.setData(framedPanel);
}
};
DnD works when I click and hold on Grid.
How I can do to DnD only worked on the header of FramedPanel.
Consider using Draggable instead of DragSource, then use the constructor that takes two arguments. This way you can specify the header as the 'handle' argument.
Draggable draggable = new Draggable(framedPanel, framedPanel.getHeader());
//assuming GXT 3, just guessing from your post
draggable.addDragStartHandler(new DragStartHandler() {
public void onDragStart(DragStartEvent event) {
//...
}
});
If you must use DragSource, subclass it to replace the Draggable instance, and create a new instance as specified above, plus making the changes found in the existing DragSource constructor.

Java swing -- Jpanel not rerendering/repainting itself

Im using a JPanel with propertyChangeListener and want it to rerender itself based on whenever a particular variable model changes. My code for the same is as follows --
public class LabelMacroEditor extends JPanel implements PropertyChangeListener {
private static final long serialVersionUID = 1L;
private LabelMacroModel model;
public LabelMacroEditor(LabelMacroModel bean) {
this.model = bean;
model.addPropertyChangeListener(this);
setupComponents();
validate();
setVisible(true);
}
public void setupComponents()
{
Box allButtons = Box.createVerticalBox();
JScrollPane macroModelScroller = new JScrollPane(allButtons);
macroModelScroller.setPreferredSize(new Dimension(300, 200));
for(MacroModel macroModel : model.getMacroModelList())
{
LabelMacroEditorEditableEntity macroEditorEntity = new LabelMacroEditorEditableEntity(macroModel);
Box entityBox = Box.createHorizontalBox();
entityBox.add(macroEditorEntity.getUpButton());
entityBox.add(Box.createHorizontalStrut(15));
entityBox.add(macroEditorEntity.getMacroDetailsButton());
entityBox.add(Box.createHorizontalStrut(15));
entityBox.add(macroEditorEntity.getDownButton());
allButtons.add(entityBox);
}
add(macroModelScroller);
}
#Override
public void propertyChange(PropertyChangeEvent arg0) {
revalidate();
repaint();
}
}
When i use the debug mode in eclipse i can see that whenever there is a change to model it triggers off the call propertyChange and it also runs over revalidate and repaint but only the JPanel display remains the same. It does not seem to be rerendering itself.
Anything fundamental that I'm missing here ?
EDIT :
An example snippet of a property im changing is as follows --
labelMacroModel.addMacroModel(addedMacroModel);
where labelMacroModel is of the type LabelMacroModel and addedMacroModel is of the type Macro
Now the relevant part of LabelMacroModel class that fires off the property change is as follows --
private List<MacroModel> macroModelList;// this is the list of all MacroModels
public void addMacroModel(MacroModel macroModel) {
macroModelList.add(macroModel);
pcs.fireIndexedPropertyChange("LabelMacroModel", macroModelList.size(), null, macroModel);
}
Its not clear how you are changing the components in the panel. If panel is not updated then repaint/revalidate will have no effect. I think you should not need revalidate/repaint to be called explicitly if you are not modifying the way components are laid out. JButton.setText should for example change the label of the button without need of calling repaint.
To expand on the answer by AKJ above, I think you should be reconstructing your components on property change. So doing a remove all then readding is one way to do this. Once you get this working you could be more selective about pushing the model update into the GUI eg if a new entry has been added then just add a new component to reflect this. The remove all / readd is fine for a lot of cases though. HTH.

Remove a generated panel in GWT after a button is clicked

I am attempting to create a Google Web Toolkit (GWT) application that also uses Google Gears, but every time I try to remove the panel, I get an exception and the panel stays there.
Here is an excerpt from the exception I get (I've only included the relevant bits of the call stack, the rest just descends into the included function below):
java.lang.AssertionError: A widget that has an existing parent widget may not be added to the detach list
at com.google.gwt.user.client.ui.RootPanel.detachOnWindowClose(RootPanel.java:122)
at com.google.gwt.user.client.ui.RootPanel.get(RootPanel.java:197)
I'm not sure what the problem is, but I really don't like leaving the button there after they approve the use of Gears.
What am I doing wrong? Or any suggestions on a different way I could do this to make it work?
if(!gearsFactory.hasPermission()) {
HorizontalPanel rightPanel = new HorizontalPanel();
rightPanel.getElement().setId("gearsPrompt");
rightPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
rightPanel.setSpacing(0);
rightPanel.setHeight("28px");
InlineLabel enableGearsText = new InlineLabel("Enable Gears for off-line access");
enableGearsText.getElement().setId("gearsText");
enableGearsText.addStyleName("titleElement");
rightPanel.add(enableGearsText);
final Button gearsButton = new Button("Use Gears");
gearsButton.getElement().setId("gearsButton");
gearsButton.addStyleName("titleElement");
gearsButton.setHeight("24px");
gearsButton.addClickHandler( new ClickHandler() {
public void onClick(ClickEvent event) {
Factory gearsFactory = Factory.getInstance();
if(gearsFactory != null) {
if(gearsFactory.getPermission()) {
RootPanel gearsPrompt = RootPanel.get("gearsPrompt");
gearsPrompt.removeFromParent();
}
}
}
});
rightPanel.add(gearsButton);
RootPanel titleBarRight = RootPanel.get("titleBarRight");
titleBarRight.add(rightPanel);
}
One solution I've found is to loop through all of the widgets under the "titleBarRight" panel and remove all widgets it contains:
if(gearsFactory.getPermission()) {
RootPanel titleBarRight = RootPanel.get("titleBarRight");
java.util.Iterator<Widget> itr = titleBarRight.iterator();
while(itr.hasNext()) {
itr.next();
itr.remove();
}
}
But somehow this still seems hacky and not quite the "right way to do it."
I know this is old, but how about...
gearsButton.addClickHandler( new ClickHandler() {
public void onClick(ClickEvent event) {
Factory gearsFactory = Factory.getInstance();
if(gearsFactory != null) {
if(gearsFactory.getPermission()) {
Button btn=(Button) event.getSource();
btn.removeFromParent();
}
}
}
});
Is there any reason for using RootPanel.get("gearsPrompt").removeFromParent(); instead of your own rightPanel.removeFromParent();? The reference is already there.
You can do :
theParentWidget.remove(index);
and the first child corresponds to 0;

Categories