Using GWT I am displaying an image thumbnail with a ClickHandler that then shows the full image (can be several MB) in a centered PopupPanel. In order to have it centered the image must be loaded before the popup is shown, otherwise the top-left corner of the image is placed in the middle of the screen (the image thinks it is 1px large). This is the code I am using to do this:
private void showImagePopup() {
final PopupPanel popupImage = new PopupPanel();
popupImage.setAutoHideEnabled(true);
popupImage.setStyleName("popupImage"); /* Make image fill 90% of screen */
final Image image = new Image();
image.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
popupImage.add(image);
popupImage.center();
}
});
image.setUrl(attachmentUrl + CFeedPostAttachment.ATTACHMENT_FILE);
Image.prefetch(attachmentUrl + CFeedPostAttachment.ATTACHMENT_FILE);
}
However, the LoadEvent event is never fired, and thus the image is never shown. How can I overcome this? I want to avoid using http://code.google.com/p/gwt-image-loader/ because I do not want to add extra libraries if I can avoid it at all. Thanks.
The onLoad() method will only fire once the image has been loaded into the DOM. Here is a quick workaround:
...
final Image image = new Image(attachmentUrl + CFeedPostAttachment.ATTACHMENT_FILE);
image.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
// since the image has been loaded, the dimensions are known
popupImage.center();
// only now show the image
popupImage.setVisible(true);
}
});
popupImage.add(image);
// hide the image until it has been fetched
popupImage.setVisible(false);
// this causes the image to be loaded into the DOM
popupImage.show();
...
Hope that helps.
Related
I am creating a game with a few friends, and I am currently working on the main menu. I figured out how to get regular old TextButtons, but ImageTextButtons are giving me a very hard time. I have two microphone images, one on and one off, and it should change when the user clicks it. I used a Texture Packing program, as part of this tutorial: https://www.youtube.com/watch?v=YPxd_xbnIpk
One of the numerous solutions I've been using is as follows:
MenuState Class-
Private skin = new Skin;
TextureAtlas buttonAtlas = new TextureAtlas ("mutebuttons.pack");
skin.addRegions(buttonAtlas);
TextButtonStyle buttonStyle = new TextButtonStyle();
ImageTextButtonStyle buttonStyle2 = new ImageTextButtonStyle();
buttonStyle.up = skin.getDrawable("soundIconON");
buttonStyle.down = skin.getDrawable("soundIconOFF");
muteButtons.pack contains the on and off mic image already (soundIconON/OFF).
Let me know if you require any more info, and thanks ahead of time.
Ed
Buttons check them selfs automatically. You don't need to do anything special and can always get the checked state by .isChecked. A button starts by default unchecked but you can change the button to checked when you create it by setChecked(true).
If you want to change the look of a button depending on it's checked state all you have to do is add the drawable. Internally it does something like If no checked state image just use default image.
Now for the type of button I think you will be fine with just a image button but any of the buttons can create a button with changeable looks. The ImageButton just allows you to add a image over the background of the button. These are the styles for the 3 different buttons:
TextButton.TextButtonStyle textButtonStyle =
new TextButton.TextButtonStyle(
Drawable up, //Background for up state
Drawable down, //background for down state
Drawable checked, //background for checked == true
BitmapFont font); //font
ImageButton.ImageButtonStyle imageButtonStyle =
new ImageButton.ImageButtonStyle(
Drawable up,
Drawable down,
Drawable checked,
Drawable imageUp, //Image for up state
Drawable imageDown, //Image for down state
Drawable imageChecked, //Image for checked == true
BitmapFont font);
//Never actually used this one, you made me aware of it's excistance. I think this is a redundant class.
ImageTextButton.ImageTextButtonStyle imageTextButtonStyle =
new ImageTextButton.ImageTextButtonStyle(
Drawable up,
Drawable down,
Drawable checked,
BitmapFont font);
So all you need to do is set the checked drawable and start clicking the button.
You can set these in a skin files as well, just call the proper drawable names from json. This is how I create a simple toggle button using text button.
com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle:
{
default: { up: my_up_button, checked: my_checked_button, font: default-font, fontColor: white }
}
If I don't want text over it just hand a empty string. Alternatively you can alter the text on a click as well.
final TextButton button = new TextButton("Ewwww! Touch me!", skin);
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
if (button.isChecked())
{
button.setText("Now I am unchecked!");
}
else
{
button.setText("Now I am checked!");
}
}
});
button img size in the grid layout doesnt change whatever I do. Following is my code. if i scale the placeholder it hav no effect as well. The space that takes by padding and margin stays when i set padding and margin to zero as well. How can i make it compact and get rid of that gap between images..
GridLayout gr = new GridLayout(1,2);
gr.setAutoFit(true);
Container grid = new Container(gr);
grid.setUIID("containerGridImgGallery");
grid.getAllStyles().setPadding(0, 0, 0, 0);
grid.getAllStyles().setMargin(0,0,0,0);
f.addComponent(BorderLayout.CENTER,grid);
placeholder = (EncodedImage) r.getImage("switch_on.png");
//if I change the scaled value of placeholder, the img size doesnt change in the grid eg scaledEncoded(screenWidth / 3, screenWidth / 3) doesnt change the img size
placeholder = placeholder.scaledEncoded((screenWidth / 2)-10, screenWidth / 3);
EncodedImage a = URLImage.createToStorage(placeholder , galleryPhotoTitle + offset + imageId, galleryPhotoUrl, URLImage.RESIZE_SCALE_TO_FILL);
final Button btn = new Button(a);
btn.setUIID("galleryGridButton");
btn.getAllStyles().setPadding(0, 0, 0, 0);
btn.getAllStyles().setMargin(0,0,0,0);
i need grid Layout here since i can set to gridLayout.autofit() in gridLayout which is what i just wanted to auto fit the images as per the screens.How can i fit the grid cells to that of the button inside it? can i set the size of the grid?
updates:
//how to use scaleImageLabel in button? i got it work somehow but not correctly i guess
EncodedImage a = URLImage.createToStorage(largePlaceholder, galleryPhotoTitle + offset + imageId, galleryPhotoUrl, URLImage.RESIZE_SCALE_TO_FILL);
final Button btn = new Button(a);
Image abc = btn.getIcon();
ScaleImageLabel scaledPlaceholder = new ScaleImageLabel(abc);
Container imageHolder = new Container();
imageHolder.addComponent(btn);
btn.setPreferredSize(new Dimension(1,1));
imageHolder.addComponent(scaledPlaceholder);
imageHolder.setLeadComponent(btn);
grid.addComponent(i, imageHolder);
i have a couple of questions:
1)why can't i set the uiid of scaledPlaceholder above (ScaledImageLabel)
it takes some of padding & margins which i want to remove. If i set uiid the images
do not appear.
2)how does setBackgroundType() work? it doesnot take setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT).
3)And most importantly how can i fit the images in the grid maintaining the aspect ratio?
if i do smth like - abc = abc.scaled(230, 336);
It fits in the grid but doesnt keep the aspect ratio of the image.
Updates 1:
EncodedImage a = URLImage.createToStorage(largePlaceholder, galleryPhotoTitle + offset + imageId, galleryPhotoUrl, URLImage.RESIZE_SCALE_TO_FILL);
ScaleImageButton scaleImageButton = new ScaleImageButton(a);
scaleImageButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//......
}
});
grid.addComponent(i, btn);
exception:
java.lang.NullPointerException
at userclasses.StateMachine$ScaleImageButton.calcPreferredSize(StateMachine.java:500)
at com.codename1.ui.Component.preferredSizeImpl(Component.java:1930)
at com.codename1.ui.Component.preferredSize(Component.java:1965)
at com.codename1.ui.Component.getPreferredSize(Component.java:752)
at com.codename1.ui.Component.getPreferredW(Component.java:832)
at com.codename1.ui.layouts.GridLayout.getPreferredSize(GridLayout.java:153)
at com.codename1.ui.Container.calcPreferredSize(Container.java:1793)
at com.codename1.ui.Component.preferredSizeImpl(Component.java:1930)
at com.codename1.ui.Component.preferredSize(Component.java:1965)
at com.codename1.ui.Component.getPreferredSize(Component.java:752)
at com.codename1.ui.Component.getPreferredW(Component.java:832)
at com.codename1.ui.layouts.GridLayout.getPreferredSize(GridLayout.java:153)
at com.codename1.ui.Container.calcPreferredSize(Container.java:1793)
at com.codename1.ui.Component.calcScrollSize(Component.java:782)
at com.codename1.ui.Component.getScrollDimension(Component.java:769)
at com.codename1.ui.Container.isScrollableY(Container.java:1873)
at com.codename1.ui.Component.isScrollable(Component.java:1686)
at com.codename1.ui.Form.isScrollable(Form.java:3058)
at com.codename1.ui.Component.checkAnimation(Component.java:3802)
at com.codename1.ui.Component.initComponentImpl(Component.java:4209)
at com.codename1.ui.Container.initComponentImpl(Container.java:843)
at com.codename1.ui.Form.initComponentImpl(Form.java:1608)
at com.codename1.ui.Display.setCurrent(Display.java:1332)
at com.codename1.ui.Form.show(Form.java:1588)
at com.codename1.ui.Form.show(Form.java:1566)
at com.codename1.ui.util.UIBuilder.showForm(UIBuilder.java:2515)
at com.codename1.ui.util.UIBuilder.showForm(UIBuilder.java:2561)
at userclasses.StateMachine.showGalleryImage(StateMachine.java:159)
at userclasses.StateMachine$1.lambda$readResponse$0(StateMachine.java:136)
at userclasses.StateMachine$1$$Lambda$17/1247957021.actionPerformed(Unknown Source)
at com.codename1.ui.util.EventDispatcher.fireActionEvent(EventDispatcher.java:345)
at com.codename1.ui.Button.fireActionEvent(Button.java:397)
at com.codename1.ui.Button.released(Button.java:428)
at com.codename1.ui.Button.pointerReleased(Button.java:516)
at com.codename1.ui.Form.pointerReleased(Form.java:2560)
at com.codename1.ui.Form.pointerReleased(Form.java:2496)
at com.codename1.ui.Component.pointerReleased(Component.java:3108)
at com.codename1.ui.Display.handleEvent(Display.java:2017)
at com.codename1.ui.Display.edtLoopImpl(Display.java:1065)
at com.codename1.ui.Display.mainEDTLoop(Display.java:994)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
error occured in here
#Override
protected Dimension calcPreferredSize() {
Image i = getIcon();
Style s = getStyle();
//error occured here
return new Dimension(i.getWidth() + s.getPaddingLeft(false) + s.getPaddingRight(false), i.getHeight()
+ s.getPaddingTop() + s.getPaddingBottom());
}
One more thing if i use label instead of btn it works fine but same doesnt work in case of button why is that?
Update 2: after adding getIconFromState method, blank form is displayed - same old problem and if null checker is removed, following error
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.codename1.impl.javase.Executor$1$1.run(Executor.java:100)
at com.codename1.ui.Display.processSerialCalls(Display.java:1149)
at com.codename1.ui.Display.mainEDTLoop(Display.java:966)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
Caused by: java.lang.NullPointerException
at userclasses.StateMachine$ScaleImageButton.calcPreferredSize(StateMachine.java:303)
at com.codename1.ui.Component.preferredSizeImpl(Component.java:1930)
at com.codename1.ui.Component.preferredSize(Component.java:1965)
at com.codename1.ui.Component.getPreferredSize(Component.java:752)
at com.codename1.ui.Component.getPreferredW(Component.java:832)
at com.codename1.ui.layouts.GridLayout.getPreferredSize(GridLayout.java:153)
at com.codename1.ui.Container.calcPreferredSize(Container.java:1793)
at com.codename1.ui.Component.preferredSizeImpl(Component.java:1930)
at com.codename1.ui.Component.preferredSize(Component.java:1965)
at com.codename1.ui.Component.getPreferredSize(Component.java:752)
at com.codename1.ui.Component.getPreferredH(Component.java:842)
at com.codename1.ui.layouts.BoxLayout.layoutContainer(BoxLayout.java:91)
at com.codename1.ui.Container.doLayout(Container.java:1366)
at com.codename1.ui.Container.layoutContainer(Container.java:1358)
at com.codename1.ui.Container.doLayout(Container.java:1371)
at com.codename1.ui.Container.layoutContainer(Container.java:1358)
at com.codename1.ui.Container.revalidate(Container.java:1006)
at com.codename1.ui.Form.setFocused(Form.java:1922)
at com.codename1.ui.Form.initFocused(Form.java:1553)
at com.codename1.ui.Form.show(Form.java:1584)
at com.codename1.ui.Form.show(Form.java:1566)
at com.codename1.ui.util.UIBuilder.showForm(UIBuilder.java:2515)
at com.codename1.ui.util.UIBuilder.showForm(UIBuilder.java:2561)
at generated.StateMachineBase.startApp(StateMachineBase.java:56)
at generated.StateMachineBase.<init>(StateMachineBase.java:31)
at generated.StateMachineBase.<init>(StateMachineBase.java:98)
at userclasses.StateMachine.<init>(StateMachine.java:51)
at com.mycompany.myapp.MyApplication.start(MyApplication.java:23)
... 9 more
Update 3:
screenshot looks like this now:
portrait:
landscape:
However if i go to landscape mode from portrait mode and again to portrait mode the images get adjusted as expected but i can still see the thin duplicate image portion there as well.
screenshot going from portrait to landscape and again to portrait:
Once the images are downloaded and match the placeholder size they are stored/cached in the system. Since Label (or Button that derives it) doesn't scale the icon image this won't change.
Changing the placeholder size after downloading won't have an effect either.
For 3.3 we introduced a new ScaleImageLabel class that should allow the label to scale to take up the additional space in such a situation. Notice that artifacts may apply due to scaling.
Since you need a Button and not a label try something like this:
public class ScaleImageButton extends Button {
/**
* Default constructor
*/
public ScaleImageButton() {
setUIID("Label");
setShowEvenIfBlank(true);
setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
}
/**
* Create a version with the given image
* #param i image
*/
public ScaleImageButton(Image i) {
setUIID("Label");
setShowEvenIfBlank(true);
setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FIT);
setIcon(i);
}
/**
* Sets the behavior of the background to one of Style.BACKGROUND_IMAGE_SCALED_FIT,
* Style.BACKGROUND_IMAGE_SCALED_FILL, Style.BACKGROUND_IMAGE_SCALE
* #param behavior the background behavior
*/
public void setBackgroundType(byte behavior) {
getUnselectedStyle().setBackgroundType(behavior);
getSelectedStyle().setBackgroundType(behavior);
getPressedStyle().setBackgroundType(behavior);
}
public byte getBackgroundType() {
return getUnselectedStyle().getBackgroundType();
}
#Override
protected Dimension calcPreferredSize() {
Image i = getIcon();
if(i == null) {
return new Dimension();
}
Style s = getStyle();
return new Dimension(i.getWidth() + s.getPaddingLeft(false) + s.getPaddingRight(false), i.getHeight() +
s.getPaddingTop() + s.getPaddingBottom());
}
public void setIcon(Image i) {
getUnselectedStyle().setBgImage(i);
getSelectedStyle().setBgImage(i);
getPressedStyle().setBgImage(i);
}
public Image getIcon() {
return getUnselectedStyle().getBgImage();
}
#Override
public void setText(String text) {
}
#Override
public Image getIconFromState() {
return getIcon();
}
#Override
public void setUIID(String id) {
Image icon = getIcon();
super.setUIID(id);
setIcon(icon);
}
}
want to animate my logo by zooming it to an splash screen.
tried the following so far:
#Override
protected void postSpash1(Form f) {
findLogoLabel(f).setPreferredW(findLogoLabel(f).getPreferredW() * 5);
findAnimateContainer(f).animateLayoutAndWait(2000);
findLogoLabel(f).setPreferredSize(null);
}
The image doesn't animate and enlarges itself. However it changes its size abruptly after 2 sec which is not what I'm looking for. I want the zooming effect(the img should grow bigger slowly to a certain extent)
I tried other ways too, but the label moves from up to down smoothly instead of bg img getting bigger
findLogoLabel(f).setPreferredH(findLogoLabel(f).getPreferredH() * 3);
findAnimateContainer(f).animateLayoutAndWait(2000);
findLogoLabel(f).setPreferredSize(null);
PS: I set the bg image in logoLabel (Label) , Animatecontainer is the container that contains logoLabel.
Blocking API's are somewhat tricky as they might collide with some other behaviors preventing the rest of the current dispatch thread from finishing its job.
Also you set the null after animating instead of before...
So in your case this should work (with old Java 5 syntax):
#Override
protected void postSpash1(final Form f) {
findLogoLabel(f).setPreferredW(findLogoLabel(f).getPreferredW() * 5);
Display.getInstance().callSerially(new Runnable() {
public void run() {
findLogoLabel(f).setPreferredSize(null);
findAnimateContainer(f).animateLayoutAndWait(2000);
}
});
}
With cool Java 8 lambdas:
#Override
protected void postSpash1(final Form f) {
findLogoLabel(f).setPreferredW(findLogoLabel(f).getPreferredW() * 5);
Display.getInstance().callSerially(() -> {
findLogoLabel(f).setPreferredSize(null);
findAnimateContainer(f).animateLayoutAndWait(2000);
});
}
public void dropAccept(final DropTargetEvent event)
{
if (TextTransfer.getInstance().isSupportedType(event.currentDataType))
{
final String d=(String)TextTransfer.getInstance().nativeToJava(event.CurrentDataType);
GC gc = new(text);
//text is the name assigned to the Canvas
text.addPaintListener(new PaintListener()
{
public void paintControl(PaintEvent e)
{
int x= event.x- shell.getBounds().x - text.getBounds().x;
int y=event.y - shell.getBounds().y - text.getBounds().y;
e.gc.drawString(d, x, y);
}
}); } }
This code snippet is part of a larger class that implements drag drop of text onto a canvas. The problem is that, the actual dropping of text is not seen on the canvas after I drop it but only after I minimize the shell and then maximize it again. Can anyone please tell me how I can make drop actions immediately visible by modifying this code?
You have not done anything to cause the control to be redrawn. Call
text.redraw();
to request that the control is redrawn (by calling the paint listener).
Note: If you add paint listeners on every drop you are going to end up with lots of listeners registered.
I am using the following code to set a tray icon in Windows and Linux. It works wonderful in Windows and works okay in Linux. In Linux (Ubuntu) I have my panel set to be (somewhat) transparent and when I add a GIF (with a transparent background) the background of the icon shows up all grey and ugly (see image, green diamond "!")....Any ideas on how to make the GIF image I am adding "keep" its transparent background?
alt text http://unarm.org/stackoverflow/panel_task.jpg
and the image I am using, if you'd like to test:
alt text http://unarm.org/stackoverflow/green_info.gif
import java.awt.*;
import java.awt.event.*;
public class TrayFun {
static class ShowMessageListener implements ActionListener {
TrayIcon trayIcon;
String title;
String message;
TrayIcon.MessageType messageType;
ShowMessageListener(
TrayIcon trayIcon,
String title,
String message,
TrayIcon.MessageType messageType) {
this.trayIcon = trayIcon;
this.title = title;
this.message = message;
this.messageType = messageType;
}
public void actionPerformed(ActionEvent e) {
trayIcon.displayMessage(title, message, messageType);
}
}
public static void main(String args[]) {
Runnable runner = new Runnable() {
public void run() {
if (SystemTray.isSupported()) {
final SystemTray tray = SystemTray.getSystemTray();
Image image = Toolkit.getDefaultToolkit().getImage("green_info.png");
PopupMenu popup = new PopupMenu();
final TrayIcon trayIcon = new TrayIcon(image, "The Tip Text", popup);
trayIcon.setImageAutoSize(true);
MenuItem item = new MenuItem("Close");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tray.remove(trayIcon);
}
});
popup.add(item);
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println("Can't add to tray");
}
} else {
System.err.println("Tray unavailable");
}
}
};
EventQueue.invokeLater(runner);
}
}
The problem lies in the sun.awt.X11.XTrayIconPeer.IconCanvas.paint() method!
Before painting, the icon background is amateurishly cleared by simply drawing a rectangle of IconCanvas’ background color, to allow image animations.
public void paint(Graphics g) {
if (g != null && curW > 0 && curH > 0) {
BufferedImage bufImage = new BufferedImage(curW, curH, BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = bufImage.createGraphics();
if (gr != null) {
try {
gr.setColor(getBackground());
gr.fillRect(0, 0, curW, curH);
gr.drawImage(image, 0, 0, curW, curH, observer);
gr.dispose();
g.drawImage(bufImage, 0, 0, curW, curH, null);
} finally {
gr.dispose();
}
}
}
}
see: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6453521
For those looking for a "real" solution, I developed a small library that is capable of displaying the tray icon honoring the transparency and also accepts SVG icons (for all platforms):
http://skype2gmail.blogspot.com/2011/05/java-tray-icon-transparency.html
It is an open source library and the source code can be found here:
https://github.com/taksan/native-tray-adapter
The library work arounds the problem by providing a JNI alternative (with GTK) when running under linux.
Chances are this problem cannot be resolved. It depends on wether Java is doing a good job in creating the tray subwindow in Linux or not. If Jave does it wrong, transparency is already lost when the image is drawn.
What is the real background value of the icon you are using? Is it the gray tone shown above? Set it to purple to see if the transparency of the image is used (Java defaults to gray background) or not.
Make sure you tried both transparency options of PNG: transparent color index as well as alpha channel. Alpha channel is very common in Linux, not so in the Windows world.
The resolution of your icon is too small. Do it in 64x64 or better 128x128. AFAIK there is no standard resolution for tray icons, and even if so, it is certainly not 16x16.
Another format you could try is SVG. Only try that after making sure that the transparency of the image is the problem (see 1).
See here for background information on this issue:
http://www.rasterman.com/index.php?page=News (scroll down to 2 February 2006)
JDIC has a tray icon, they might support transparency in linux...
https://jdic.dev.java.net/
Have you tried converting it to a .PNG (with transparency) instead? I've found they tend to be better supported by Java (In my experience)
its not that . . . this is happing because it is using the default GNOME theme for rendering the transparency - it has nothing to do with the image it self - this is an adobe air / gnome conflict - if you switch to a gnome theme were the default background is grey then it would be grey instead of white. It uses the system default image so even if it was set but the theme for the panel to have a BG image to make it look glossy like vista for example than it would do that. Adobe Air / Java doesn't know that you over road the theme default with transparency and therefor it is using the system default