GWT - Google visualization problems using layout panels? - java

I'm having troubles in my GWT app with a Google Visualization chart not showing up until after the user has some sort of interaction with the window (e.g. moves the mouse across the screen or presses a button). This would be fine except that the chart is suppose to show up as the first thing the user sees and since it's meant to be seen on a mobile device, it's likely they will not see the chart because their first interaction will be clicking a button that hides the chart to show other information.
Using the "Getting started tutorial" over at the Visualization code's page, the chart loads immediately fine (once some slight changes are made the fix the problems from the slightly out of date tutorial). After some trial and error to find where the difference between my code and the example code that was causing the problem, I found that it's happening because my code is using the newer layout panels instead of just regular panels in GWT.
The below code is the working tutorial code changed so that it uses a RootLayoutPanel.get() instead of a RootPanel.get(). With this, the chart doesn't load until you click to reload the page, then you can see the chart for an instant before the page reloads. This should be easily tested with the below code. To get the chart to show up for the entire time, simply change RootLayoutPanel.get() to RootPanel.get().
Something in my app is allowing the chart to load after user interaction (I'm not sure what). However, the layout panel is certainly the problem as if I change it to a regular panel it works fine. Unfortunately, my entire app is built using layout panels.
What's going on and how might I be able to make the chart show up from the start using layout panels? Thank you much!
package com.test.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.visualization.client.AbstractDataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.Selection;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.events.SelectHandler;
import com.google.gwt.visualization.client.visualizations.corechart.PieChart;
import com.google.gwt.visualization.client.visualizations.corechart.Options;
public class SimpleViz implements EntryPoint {
public void onModuleLoad() {
// Create a callback to be called when the visualization API
// has been loaded.
Runnable onLoadCallback = new Runnable() {
public void run() {
LayoutPanel panel = RootLayoutPanel.get();
// Create a pie chart visualization.
PieChart pie = new PieChart(createTable(), createOptions());
pie.addSelectHandler(createSelectHandler(pie));
panel.add(pie);
}
};
// Load the visualization api, passing the onLoadCallback to be called
// when loading is done.
VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);
}
private Options createOptions() {
Options options = Options.create();
options.setWidth(400);
options.setHeight(240);
options.setTitle("My Daily Activities");
return options;
}
private SelectHandler createSelectHandler(final PieChart chart) {
return new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
String message = "";
// May be multiple selections.
JsArray<Selection> selections = chart.getSelections();
for (int i = 0; i < selections.length(); i++) {
// add a new line for each selection
message += i == 0 ? "" : "\n";
Selection selection = selections.get(i);
if (selection.isCell()) {
// isCell() returns true if a cell has been selected.
// getRow() returns the row number of the selected cell.
int row = selection.getRow();
// getColumn() returns the column number of the selected cell.
int column = selection.getColumn();
message += "cell " + row + ":" + column + " selected";
} else if (selection.isRow()) {
// isRow() returns true if an entire row has been selected.
// getRow() returns the row number of the selected row.
int row = selection.getRow();
message += "row " + row + " selected";
} else {
// unreachable
message += "Pie chart selections should be either row selections or cell selections.";
message += " Other visualizations support column selections as well.";
}
}
Window.alert(message);
}
};
}
private AbstractDataTable createTable() {
DataTable data = DataTable.create();
data.addColumn(ColumnType.STRING, "Task");
data.addColumn(ColumnType.NUMBER, "Hours per Day");
data.addRows(2);
data.setValue(0, 0, "Work");
data.setValue(0, 1, 14);
data.setValue(1, 0, "Sleep");
data.setValue(1, 1, 10);
return data;
}
}

With the Layout panels the sizing of the widgets is done in JavaScript. When the initial page is loaded the initial sizing is done after everything else is finished. However in your case the pie is added when the library is loaded and that runs after the initial sizing. Therefor your widget isn't sized and won't show up. You need to call panel.forceLayout(); explicitly as the last method in you run method.

The google chart tools definately work with LayoutPanels. I am using it myself.
It's really difficult to say what's wrong but here are a couple of suggestions:
Check with Chrome Dev Tools (Console) if an exception is thrown.
Do you have standard mode enabled. That's important with LayoutPanels (make sure you have <!DOCTYPE html> in your HTML host page
You could try a 3rd party wrapper (supports automatic resizes)

Related

change font in JOptionPane.showInputDialog

I'm writing a program in java language and I want to make some changes in one part of my JOptionPane.showInputDialog. My dialog is this :
JOptionPane.showInputDialog("Total Amount Deposited:\t\t" +
totalAmount + "\n Enter Coin Value \n" + "(Enter 1 to stop)");
and I want to make the part that is saying (Enter 1 to stop) a little bit smaller than the other parts.
I'm beginner in java language (roughly 2 months :D) and don't have any other experience. so, please keep your answers simple. thanks in advance.
A JOptionPane will display the text in a JLabel, which supports basic HTML. So you will need to wrap your text string in HTML, then you can use different fonts, colors or whatever.
Simple example:
String text = "<html>Normal text <b>and bold text</b></html>";
JOptionPane.showInputDialog(text);
You can also use Font.pointSize() or Font.size() from java.awt.Font.
Create a String = "the text"
put in a label pa
use setFont();
Quick example :
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Test extends JFrame {
public static void main(String[] args)
{
String a = "(enter 1 to stop)";
JLabel pa = new JLabel();
JFrame fr = new JFrame();
fr.setSize(200,200);
pa.setText(a);
pa.setFont(pa.getFont().deriveFont(11.0f)); //change the font size from here
fr.add(pa);
fr.setVisible(true);
}
}
For JDK 8.x, I find the following works to enlarge the font size of most portions of the built-in JOptionPane.showInputDialog, especially buttons, textboxes and comboboxes.
It is mostly generic, except for the two parts I want to be bold font.
It even allows for exceptions (think of it as an "all except" strategy) when you want to enlarge 99% of the pieces of an input dialog, except for one or two pieces.
Sorry for the bad formatting, but the "Code Sample" tool messed up everything and I don't have time to fix it.
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.swing.*;
/**
* Changes the font size used in JOptionPane.showInputDialogs to make them more
* ADA section 508 compliant by making the text size larger, which is very nice
* for older people and anyone else with vision problems.
*
* #param fontSize
* - size of the font in pixels
*/
private static void makeDialogsEasierToSee(int fontSize)
{
// This next one is very strange; but, without it,
// any subsequent attempt to set InternalFrame.titleFont will
// be ignored, so resist the temptation to remove it.
JDialog.setDefaultLookAndFeelDecorated(true);
// define normal and bold fonts that we will use to override the defaults
Font normalFont = new Font(Font.MONOSPACED, Font.PLAIN, fontSize);
Font boldFont = normalFont.deriveFont(Font.BOLD);
// get a list of objects that we can try to adjust font size and style for
List<Map.Entry<Object, Object>> entries = new ArrayList<>(UIManager.getLookAndFeelDefaults().entrySet());
// System.out.println(entries.size());
// remove anything that does NOT involve font selection
entries.removeIf(filter -> filter.getKey().toString().indexOf(".font") == -1);
// System.out.println(entries.size());
// Define a list of font sections of the screen that we do NOT want to
// enlarge/bold.
// The following is specific to jKarel so we do not obscure the display of
// "beeper piles" on the maps.
List<String> exempt = Arrays.asList("Panel.font");
// remove anything on the exempt list
entries.removeIf(filter -> exempt.contains(filter.getKey().toString()));
// System.out.println(entries.size());
// optional: sort the final list
Collections.sort(entries, Comparator.comparing(e -> Objects.toString(e.getKey())));
// apply normal font to all font objects that survived the filters
for (Map.Entry<Object, Object> entry : entries)
{
String key = entry.getKey().toString();
// System.out.println(key);
UIManager.put(key, normalFont);
}
UIManager.put("Label.font", boldFont);
UIManager.put("InternalFrame.titleFont", boldFont);
}
You basically have two straightforward options - Switch to JDialog or use HTML.
JOptionPane is intended for simple messages or interaction with the users. JDialog is a better choice if you want to break out of the canned use cases, and as you get more complex you will probably eventually have to switch to it.
To meet your immediate use case, you can send in an html message. The rules are:
You must begin and end with <html></html> tags. Put them in the middle and nothing happens.
You must remove all "\n"'s in your code. They don't work in html
anyway and the JPanel tries to use each line, as defined by \n's as a
separate html doc. Switch to
int totalAmount = 345; //for testing
String message = "<html>"
+ "Total Amount Deposited: " + totalAmount
+ "<br> Enter Coin Value "
+ "<br><span style='font-size:10'>(Enter 1 to stop)</span>"
+ "</html>";
JOptionPane.showInputDialog(message);

Designing UI in Kindle KDK (extended java.awt)

I have some experience with Android development and now I have decided to learn something new - developing for Kindle (NOT Android based Kindle Fire).
Amazon offers KDK + Personal Basis Profile 1.1.2 (JSR 217) as a platform.
My problem is, how to design UI. I do not have any experience with awt (just did som apps in java swing), but is doesn't seem to be a big issue, because it's quite simple... Main issue is with 'replacing' android's ListView.
I've tried to use component named KPages. I'm, however, not able to put anything else but KLabel into the pages model...
PageProvider pp = PageProviders.createKBoxLayoutProvider(KBoxLayout.PAGE_AXIS);
final KPages pages = new KPages(pp);
for (int i = 0; i < 40; i++) {
final KPanel listItem = new KPanel();
// listItem.add(new KLabelMultiline("label numero " + i + " is not very good, because it will be displayed over more than one line and 'pages' won't be able to deal with it"));
listItem.add(new KLabel("label numero " + i + " is very good, because it won't be displayed over more than one line and 'pages' will be able to deal with it"));
listItem.add(new KButton("read"));
listItem.add(new KButton("edit"));
pages.addItem(listItem);
}
context.getRootContainer().add(pages);
Sample code above shows my effort to list some items. KPages works well only when adding KLabel using pages.addItem(). Just inserting KLabelMultiline causes paging to mulfunction (instead of showing labels 0-12 it 'displays' 0-26 as in single line, but screen of kindle shows only 14-26). Trying to insert whole KPanel with label and 2 buttons results in listing the labels followed by one empty line for each item, without any button... displaying same KPanel outside pages works fine - I can see the label and both buttons...
I'm almost sure it's my fault for leaving something out, but thanks to really little information available on KDK, I'm not able to find it... Can anybody give me a hand? Thanks
Try overriding the getPreferredSize, getMinimumSize, and getMaximumSize calls to your constructor for KPanel. Set width and height to whatever your screen size is.
final KPanel listItem = new KPanel() {
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public Dimension getMinimumSize() {
return new Dimension(width, height);
}
public Dimension getMaximumSize() {
return new Dimension(width, height);
}
};

How to implement freeze column in GXT 3.x?

How can frozen columns be implemented in GXT 3.x (from Sencha)? Ext-JS, another product from Sencha seems to implement this, but I can't see where the Java based GXT implement the same thing:
http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/locking-grid.html
The basic idea is that you need two different scrolling containers, one with the fixed column(s), one with the scrolling columns. Each of these need to be in a distinct viewport, so the standard Grid/GridView doesn't work well with this - they make assumptions about how scrolling should behave, so simply subclassing one or both is likely to be fairly involved.
Instead, you can build two grids, one for the locked columns, one for the scrolling ones. Each can deal with their own ColumnConfig classes, to draw headers and rows, and will be linked to the same ListStore to ensure their data is in sync - changes in the store will be passed along to both listening grids.
To get the full effect, some additional wiring will be needed:
Linking scrolling. Listen to the BodyScrollEvent from each Grid, and scroll the other to the same place (changing only top, not left, since you don't want one to control the other).
Sizing is the second big piece - both grids need their scrollable height to be the same, but the horizontal scrolling one needs a buffer on the bottom when it is actually showing that scrollbar. Usually the Grid is told to size based on its parent's instructions, though sometimes you directly size the Grid - in this case, this step is not needed, just size the two grids slightly differently. Otherwise, you'll need to structure the layout to properly configure this.
Finally, the locked column needs its vertical scrollbar to be hidden away - the user has no need to see two vertical scrollbars.
This covers the basic use case, but doesn't deal with things like alternate GridView implementations - GroupingView and subclasses will need to link expanding (and to hide the group headings so they don't appear twice, plus deal with the fact that the group row shouldn't get split when the second half scrolls sideways), TreeGridView and TreeGrid will need to link expanding nodes and hide the tree +/- icons from the second grid.
Here's this basic set of modifications applied to the basic grid example at http://www.sencha.com/examples/#ExamplePlace:basicgrid. To help avoid confusing the issue, I've deleted a number of other features in that grid such as tooltips and changing the selection model:
public class GridExample implements IsWidget, EntryPoint {
private static final StockProperties props = GWT.create(StockProperties.class);
private ContentPanel root;
#Override
public Widget asWidget() {
if (root == null) {
final NumberFormat number = NumberFormat.getFormat("0.00");
ColumnConfig<Stock, String> nameCol = new ColumnConfig<Stock, String>(props.name(), 50, SafeHtmlUtils.fromTrustedString("<b>Company</b>"));
ColumnConfig<Stock, String> symbolCol = new ColumnConfig<Stock, String>(props.symbol(), 100, "Symbol");
ColumnConfig<Stock, Double> lastCol = new ColumnConfig<Stock, Double>(props.last(), 75, "Last");
ColumnConfig<Stock, Double> changeCol = new ColumnConfig<Stock, Double>(props.change(), 100, "Change");
changeCol.setCell(new AbstractCell<Double>() {
#Override
public void render(Context context, Double value, SafeHtmlBuilder sb) {
String style = "style='color: " + (value < 0 ? "red" : "green") + "'";
String v = number.format(value);
sb.appendHtmlConstant("<span " + style + " qtitle='Change' qtip='" + v + "'>" + v + "</span>");
}
});
ColumnConfig<Stock, Date> lastTransCol = new ColumnConfig<Stock, Date>(props.lastTrans(), 100, "Last Updated");
lastTransCol.setCell(new DateCell(DateTimeFormat.getFormat("MM/dd/yyyy")));
List<ColumnConfig<Stock, ?>> l = new ArrayList<ColumnConfig<Stock, ?>>();
//Remove name from main set of columns
// l.add(nameCol);
l.add(symbolCol);
l.add(lastCol);
l.add(changeCol);
l.add(lastTransCol);
//create two column models, one for the locked section
ColumnModel<Stock> lockedCm = new ColumnModel<Stock>(Collections.<ColumnConfig<Stock, ?>>singletonList(nameCol));
ColumnModel<Stock> cm = new ColumnModel<Stock>(l);
ListStore<Stock> store = new ListStore<Stock>(props.key());
store.addAll(TestData.getStocks());
root = new ContentPanel();
root.setHeadingText("Locked Grid Sample");
root.setPixelSize(600, 300);
final Resizable resizable = new Resizable(root, Dir.E, Dir.SE, Dir.S);
root.addExpandHandler(new ExpandHandler() {
#Override
public void onExpand(ExpandEvent event) {
resizable.setEnabled(true);
}
});
root.addCollapseHandler(new CollapseHandler() {
#Override
public void onCollapse(CollapseEvent event) {
resizable.setEnabled(false);
}
});
//locked grid
final Grid<Stock> lockedGrid = new Grid<Stock>(store, lockedCm) {
#Override
protected Size adjustSize(Size size) {
//this is a tricky part - convince the grid to draw just slightly too wide
//and so push the scrollbar out of sight
return new Size(size.getWidth() + XDOM.getScrollBarWidth() - 1, size.getHeight());
}
};
lockedGrid.setView(new GridView<Stock>(){{
this.scrollOffset=0;
}});
//require columns to always fit, preventing scrollbar
lockedGrid.getView().setForceFit(true);
//main grid, with horiz scrollbar
final Grid<Stock> grid = new Grid<Stock>(store, cm);
//don't want this feature, want to encourage horizontal scrollbars
// grid.getView().setAutoExpandColumn(nameCol);
grid.getView().setStripeRows(true);
grid.getView().setColumnLines(true);
grid.setBorders(false);
grid.setColumnReordering(true);
grid.setStateful(true);
grid.setStateId("gridExample");
//link scrolling
lockedGrid.addBodyScrollHandler(new BodyScrollHandler() {
#Override
public void onBodyScroll(BodyScrollEvent event) {
grid.getView().getScroller().scrollTo(ScrollDirection.TOP, event.getScrollTop());
}
});
grid.addBodyScrollHandler(new BodyScrollHandler() {
#Override
public void onBodyScroll(BodyScrollEvent event) {
lockedGrid.getView().getScroller().scrollTo(ScrollDirection.TOP, event.getScrollTop());
}
});
HorizontalLayoutContainer gridWrapper = new HorizontalLayoutContainer();
root.setWidget(gridWrapper);
//add locked column, only 300px wide (in this example, use layouts to change how this works
HorizontalLayoutData lockedColumnLayoutData = new HorizontalLayoutData(300, 1.0);
//this is optional - without this, you get a little offset issue at the very bottom of the non-locked grid
lockedColumnLayoutData.setMargins(new Margins(0, 0, XDOM.getScrollBarWidth(), 0));
gridWrapper.add(lockedGrid, lockedColumnLayoutData);
//add non-locked section, taking up all remaining width
gridWrapper.add(grid, new HorizontalLayoutData(1.0, 1.0));
}
return root;
}
#Override
public void onModuleLoad() {
RootPanel.get().add(asWidget());
}
}
There are a handful of issues (no line between locked and unlocked column, locked column header menu context icon is slightly out of place), but it covers most of the details without much hassle, and leaves almost all of it open to configuration - want the lock at the end? Just move the modifications around - want more than one locked column? just add more to the lockedCm.
That functionality is not implemented in GXT, but there is an user called The_Jackal who made a workaround for this problem in the Sencha Forum - Thread. I haven't tried yet, but I hope it can help you.
GXT - Freeze grid workaround Download

How to prevent JComboBox drop-down list from exceeding vertical screen size

I use a JComboBox with many entries (hundreds). I want to limit the size of its drop-down list to the vertical size of the screen. Using a fixed size does not work out properly for different look&feels and screen resolutions.
I am using Java 6u25 on Windows 7.
If I set the maximum row count to a value (e.g. 100) that exceeds the number of list items (=rows) that fit on the screen (75), the drop-down list seems to be drawn in full size but the lowest entries are never visible.
Here is a screenshot for illustation (thanks for the SSCCE by #trashgod). The sceenshot was taken in a virtual machine on XP.
I also tested the code on another PC, so I think I can rule out some driver issues.
What I like to have is a drop-down list that fits on screen where I can scroll down completely to the very last value (and see that value). The other way round, I would like to see the scroll down button of the scrollbar.
Is the only possibility to render a cell of the list and use this in my calculations? Manipulation of height parameters of the combobox did not work.
Any ideas how to solve this?
What puzzles me is that I did not find any reference to that problem whatsoever. I assume that I am either missing something obvious here or that I am using the wrong keywords for my search. If any of the latter two, my apologies please give me a hint.
Thanks.
I find this description hard to believe. Can you back it up with an SSCCE?
Your skepticism is well founded; my description was based on a distant memory of a remote implementation. With the sscce below, I see a scroll bar and the truncation reported by #uhm; I can only select from among the last, half-dozen, hidden entries by using the keyboard. I get similar results on these platforms:
Mac OS X: [Aqua Look and Feel for Mac OS X - com.apple.laf.AquaLookAndFeel]
Ubuntu: [The Java(tm) Look and Feel - javax.swing.plaf.metal.MetalLookAndFeel]
Windows: [The Java(tm) Look and Feel - javax.swing.plaf.metal.MetalLookAndFeel]
import java.awt.EventQueue;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
/** #see http://stackoverflow.com/questions/8270256 */
public class TallCombo extends JPanel {
private static final int N = 128;
public TallCombo() {
final JComboBox combo = new JComboBox();
for (int i = 0; i < N; i++) {
combo.addItem("Item " + Integer.valueOf(i));
}
combo.setMaximumRowCount(N / 2);
this.add(combo);
}
private void display() {
JFrame f = new JFrame("TallCombo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
System.out.println(UIManager.getLookAndFeel());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new TallCombo().display();
}
});
}
}
I found this example: http://www.javaprogrammingforums.com/awt-java-swing/11457-jcombobox-scroll-bars.html (at the bottom)

How to force a minimum height of a JFace Wizard in Eclipse?

I'm presenting a wizard (code here) that gets too low, so the content does not show completely (see screenshot below):
How can I force the wizard to have a minimum height?
According to the answer on this question here on StackOverflow, the wizard will be the same height as the largest wizardpage in the wizard, but my wizard obvilusly does not get resized according to at least the content of the largest page, and I also tried to set the minimum height of the first visible wizard page with code like this in the WizardPage class:
#Override
public void createControl(Composite parent) {
// create the composite to hold the widgets
Composite composite = new Composite(parent, SWT.NULL);
composite.setSize(300, 1024); // TODO: Does this work?
GridData gridData = new GridData(300, 1024);
gridData.heightHint = 1024;
gridData.minimumHeight = 1024;
composite.setLayoutData(gridData);
... but without success so far.
Any hints?
Try to set
parent.setLayout(new GridLayout());
to your createControl() implementation of your first page.
It appears the parent you get in that method has an instance of PageContainerFillLayout as layout, not GridLayout.
If you have access to your WizardDialog, you could also call
wizardDialog.setMinimumPageSize(300, 1024)
You may need to specify a height hint for the GridData.
Alternatively, you could use a three column GridLayout and get all the rows after the first to span columns 2 and 3. I tend to use GridLayout and haven't had this problem before.
you can use this codes below:
parent.addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent event) {
parent.setSize(parent.computeSize(490, 320));
}
});
I just had a very similar problem (on Windows): A wizard where the wizard page had no message was not shown completely. What quickly solved it for me was to just add a message with a single space in the wizard page constructor:
class Page extends WizardPage {
Page() {
super("page.id", "Page title", null);
setMessage(" ");
The accepted answer did not work for me (the wizard has quite some fields).

Categories