I want to add an icon to each items in a list an image. This is my code for creating list :
Form f3=new Form("DEMO FORM");
f3.setScrollable(true);
f3.setLayout(new BorderLayout());
f3.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
String items[] = {"one","two","three","four"};
DefaultListModel myListModel = new DefaultListModel(items);
List lst=new List(myListModel);
f3.addComponent(lst);
f3.show();
How can I do that?
Use this List Renderer
import com.sun.lwuit.Component;
import com.sun.lwuit.Font;
import com.sun.lwuit.Image;
import com.sun.lwuit.Label;
import com.sun.lwuit.List;
import com.sun.lwuit.list.ListCellRenderer;
import com.sun.lwuit.plaf.Border;
import java.io.IOException;
public class MyListRenderer extends Label implements ListCellRenderer {
private Image[] images;
/** Creates a new instance of MyListRenderer */
public MyListRenderer() {
super("");
images = new Image[2];
try {
images[0] = Image.createImage("/on.png");
images[1] = Image.createImage("/off.png");
} catch (IOException ex) {
ex.printStackTrace();
}
}
public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
setText(value.toString());
//getStyle().setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD,Font.SIZE_MEDIUM));
if (isSelected) {
setFocus(true);
setIcon(images[1]);
getStyle().setBgColor(0xffcc99);
getStyle().setBgTransparency(55);
getStyle().setBorder(Border.createRoundBorder(15, 15, 0xff9900, true));
} else {
setFocus(false);
setIcon(images[0]);
getStyle().setBgColor(0xffffff);
getStyle().setFgColor(0x000000);
getStyle().setBorder(Border.createRoundBorder(15, 15, 0xffcc99, true));
getStyle().setBgTransparency(255);
}
return this;
}
public Component getListFocusComponent(List list) {
setIcon(images[1]);
setText("");
getStyle().setBgColor(0x0000ff);//no effect
setFocus(true);
getStyle().setBgTransparency(100);
return this;
}
}
You can remove unwanted embelishments from this renderer: color changes on focus, etc, ...I have also given code for two different icons for the unselected and selected list item.
Then set the renderer of the list like this:
lst.setListCellRenderer(new MyListRenderer());
You need to place the image data in the model or provide some way for the renderer to extract and apply that data. See samples for this in the LWUIT demo where you have both the renderer demo or the Scrolling demo which show off lists that have icons and various entry layouts.
I have used newer 'Generic List Cell Renderer' to produce thumbnail(icons) in a list. I found it easier to implement than other options for list rendering. Following link has example code to show how to create list using this technique.
http://codenameone.blogspot.in/2011/03/list-rendering-easy-way-generic-list.html
To show thumbnail i did the following which is pretty much boilerplace in LWUIT.
private Container createGenericRendererContainer() throws IOException {
Container c = new Container(new BorderLayout());
c.setUIID("ListRenderer");
Label xname = new Label("");
Label description = new Label();
//create box layout to contain name and description
Container cnt = new Container(new BoxLayout(BoxLayout.Y_AXIS));
xname.setName("Name");
xname.getStyle().setBgTransparency(0);
xname.getStyle().setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
description.setFocusable(true);
description.setName("Description");
cnt.addComponent(xname);
cnt.addComponent(description);
c.addComponent(BorderLayout.CENTER, cnt);
//thumbail or icon goes here. we add to the left in our borderlayout
Button thumb = new Button(Image.createImage("/res/home-work.png"));
c.addComponent(BorderLayout.WEST, thumb);
return c;
}
Related
I have a large winform application which we working to modify the appearance. I am replacing System.Windows.Forms.Toolbar to System.Windows.Forms.ToolStrip control. I use a custom renderer to change dropdown arrow color. with default renderer i get mouse hover effects in toolstrip but with my custom rendering it dont seem to work. Here's my code.
Tool strip initialization:I removed unnecessary code for reading comfort
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.imageList1 = new System.Windows.Forms.ImageList(this.components);
this.toolStripDropDownButton1 = new System.Windows.Forms.ToolStripDropDownButton();
this.toolStrip1.ImageList = this.imageList1;
this.toolStrip1.ImageScalingSize = new System.Drawing.Size(55, 32);
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripDropDownButton1
});
this.toolStrip1.Renderer = new MyRenderer();
Toolstrip dropdown button:
this.toolStripDropDownButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.toolStripDropDownButton1.ImageIndex = 0;
this.toolStripDropDownButton1.Name = "toolStripDropDownButton1";
CustomRenderer
public class MyRenderer : ToolStripRenderer
{
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
e.ArrowColor = Color.White;
base.OnRenderArrow(e);
}
}
thanks to #LarsTech for his help. I found this working. I made this below modification in renderer and in code.
Added this line in initialization
this.Toolstip1.RenderMode = ToolStripRenderMode.Professional;
CustomRenderer
public class MyRenderer : ToolStripProfessionalRenderer //Professional renderer
{
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
e.ArrowColor = Color.White;
base.OnRenderArrow(e);
}
}
In my project I use lwuit List(main), with a custom renderer.
I`m following the purpose of implementing the expandable list item, that expands/collapses another List (wrapped).
Initially, I'd created Container with Button and List (without collapse/expand behaviour), but when I used it in main list, I faced problem with inability to select Items in wrapped list.
So, I will happy if you helps me with two problems:
Can I fix it using standard lwuit tools?
How can I hide my wrapped list by clicking HeaderBar (visibility just hides the content, but leaves a big gap)?
Images for clarity (ListItem - item of main List, which does not display on image):
private void fillForm() {
mF = new Form();
fillList1();
fillList2();
fillList();
mF.show();
}
private void fillList() {
mList = new CList();
mList.setRenderer(new CRenderer());
mList.addItem(c1);
mList.addItem(c2);
mF.addComponent(c1);
mF.addComponent(c2);
}
private void fillList1() {
c1 = new Container();
b1 = new Button();
b1.getUnselectedStyle().setBorder(Border.createLineBorder(2, 0x000000));
b1.addActionListener(this);
mList1 = new List();
mList1.setName("l1");
mList1.setRenderer(new DefaultListCellRenderer());
mList1.addItem("one");
mList1.addItem("two");
mList1.addItem("three");
mList1.addItem("four");
mList1.addItem("five");
c1.addComponent(b1);
c1.addComponent(mList1);
}
private void fillList2() {
c2 = new Container();
b2 = new Button();
b2.getUnselectedStyle().setBorder(Border.createLineBorder(2, 0x000000));
b2.addActionListener(this);
mList2 = new List();
mList2.setName("l2");
mList2.setRenderer(new DefaultListCellRenderer());
mList2.addItem("путин");
mList2.addItem("ест");
mList2.addItem("детей");
mList2.addItem("больше чем");
mList2.addItem("любит родину");
c2.addComponent(b2);
c2.addComponent(mList2);
}
private class CRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
return (Container)value; //To change body of generated methods, choose Tools | Templates.
}
}
Can this component solve your issue?
PopupChoiceGroup
So I have a TextArea and as the user pastes paragraphs into it, or just writes in it, I want it to expand vertically to reveal all the available text. I.e. not to use a scrollbar in the text field itself... much like what happens on many web pages. Many users, myself included, don't like to be forced to edit in a small window. Exactly how Facebook status updates box works.
I've tried
myTextArea.autoSize()
wrapped in an
myTextArea.textProperty().addListener(new ChangeListener()....);
but that doesn't work. I think it's happy autosizing to its current size.
The left, right & top anchors are set to it's parent AnchorPane. I've tried it with the bottom attached and not attached. Ideally I'd like to grow the anchor pane as the textarea grows.
I don't mind reading the TextProperty and calculating a trigger size which I set myself... but this seems a hacky approach IF there is already a best practise. The number of properties and sub objects of javafx is sufficiently daunting that it seems like a good point to ask the question here, rather than trying to figure out how many pixels the font/paragraphs etc are taking up.
Update:
So I thought maybe I was overthinking it, and all I needed to do was to switch the scrollbars off and the rest would happen. Alas, looking for available fields and methods for "scroll", "vertical", "vbar" comes up with nothing I can use. ScrollTopProperty looks like it's for something else.
The problem; the height of textArea is wanted to be grown or shrunk while its text is changing by either user's typing or copy-pasting. Here is another approach:
public class TextAreaDemo extends Application {
private Text textHolder = new Text();
private double oldHeight = 0;
#Override
public void start(Stage primaryStage) {
final TextArea textArea = new TextArea();
textArea.setPrefSize(200, 40);
textArea.setWrapText(true);
textHolder.textProperty().bind(textArea.textProperty());
textHolder.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
if (oldHeight != newValue.getHeight()) {
System.out.println("newValue = " + newValue.getHeight());
oldHeight = newValue.getHeight();
textArea.setPrefHeight(textHolder.getLayoutBounds().getHeight() + 20); // +20 is for paddings
}
}
});
Group root = new Group(textArea);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
// See the explanation below of the following line.
// textHolder.setWrappingWidth(textArea.getWidth() - 10); // -10 for left-right padding. Exact value can be obtained from caspian.css
}
public static void main(String[] args) {
launch(args);
}
}
But it has a drawback; the textarea's height is changing only if there are line breaks (ie Enter keys) between multiple lines, if the user types long enough the text gets wrapped to multiple line but the height is not changing.
To workaround this drawback I added this line
textHolder.setWrappingWidth(textArea.getWidth() - 10);
after primaryStage.show();. It works well for long typings where user does not linebreaks. However this generates another problem. This problem occurs when the user is deleting the text by hitting "backspace". The problem occurs exactly when the textHolder height is changed and where the textArea's height is set to new value. IMO it maybe a bug, didn't observe deeper.
In both case the copy-pasting is handling properly.
Awaiting a better, i use this hacky solution.
lookup the vertical scrollbar of the textarea.
make it transparent
listen to its visible property
when the scrollbar become visible i add a row to the textarea.
The code:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.TextArea;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class GrowGrowTextArea extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane root = new AnchorPane();
root.setStyle("-fx-padding:20;-fx-background-color:dodgerblue;");
final TextArea textArea = new TextArea();
AnchorPane.setTopAnchor(textArea, 10.0);
AnchorPane.setLeftAnchor(textArea, 10.0);
AnchorPane.setRightAnchor(textArea, 10.0);
root.getChildren().add(textArea);
primaryStage.setScene(new Scene(root, 400, 300));
primaryStage.show();
ScrollBar scrollBar = lookupVerticalScrollBar(textArea);
scrollBar.setOpacity(0.0);
scrollBar.visibleProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> source,
Boolean wasVisible,
Boolean isVisible) {
if (isVisible) {
textArea.setPrefRowCount(textArea.getPrefRowCount() + 1);
textArea.requestLayout();
}
}
});
}
private ScrollBar lookupVerticalScrollBar(Node node) {
if (node instanceof ScrollBar && ((ScrollBar)node).getOrientation() == Orientation.VERTICAL) {
return (ScrollBar) node;
}
if (node instanceof Parent) {
ObservableList<Node> children = ((Parent) node).getChildrenUnmodifiable();
for (Node child : children) {
ScrollBar scrollBar = lookupVerticalScrollBar(child);
if (scrollBar != null) {
return scrollBar;
}
}
}
return null;
}
}
I had a similar problem with creating expanding TextArea. I was creating TextArea that looks like TextField and expand vertically every time when there is no more space in line.
I have tested all solutions that I could find on this topic on stack and other sources available. I found few good solutions but neither was good enough.
After many hours of fighting, I figured out this approach.
I extended TextArea class, override layoutChildren() method and add a listener on text height.
#Override
protected void layoutChildren() {
super.layoutChildren();
setWrapText(true);
addListenerToTextHeight();
}
private void addListenerToTextHeight() {
ScrollPane scrollPane = (ScrollPane) lookup(".scroll-pane");
scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER);
StackPane viewport = (StackPane) scrollPane.lookup(".viewport");
Region content = (Region) viewport.lookup(".content");
Text text = (Text) content.lookup(".text");
text.textProperty().addListener(textHeightListener(text));
}
private InvalidationListener textHeightListener(Text text) {
return (property) -> {
// + 1 for little margin
double textHeight = text.getBoundsInLocal().getHeight() + 1;
//To prevent that our TextArena will be smaller than our TextField
//I used DEFAULT_HEIGHT = 18.0
if (textHeight < DEFAULT_HEIGHT) {
textHeight = DEFAULT_HEIGHT;
}
setMinHeight(textHeight);
setPrefHeight(textHeight);
setMaxHeight(textHeight);
};
}
I used some of the code found in the previous answers.
The growTextAreaIfNecessary method will increase the height of textArea until the scrollbar is not visible (limited to 20 lines in this example).
The problem with this approach is that the window needs to be redrawn several times until the perfect height is found.
private ScrollBar lookupVerticalScrollBar(Node node) {
if (node instanceof ScrollBar && ((ScrollBar) node).getOrientation() == Orientation.VERTICAL) {
return (ScrollBar) node;
}
if (node instanceof Parent) {
ObservableList<Node> children = ((Parent) node).getChildrenUnmodifiable();
for (Node child : children) {
ScrollBar scrollBar = lookupVerticalScrollBar(child);
if (scrollBar != null) {
return scrollBar;
}
}
}
return null;
}
private void growTextAreaIfNecessary(TextArea textArea) {
Platform.runLater(() -> {
ScrollBar lookupVerticalScrollBar = lookupVerticalScrollBar(textArea);
int prefRowCount = textArea.getPrefRowCount();
if (lookupVerticalScrollBar.isVisible() && prefRowCount < 20) {
textArea.setPrefRowCount(prefRowCount + 1);
System.out.println("increasing height to: " + (prefRowCount + 1));
growTextAreaIfNecessary(textArea);
}
});
}
I have tried many hacks, most of them had jitters while typing, this to me was the perfect result:
textArea.textProperty().addListener((obs,old,niu)->{
Text t = new Text(old+niu);
t.setFont(textArea.getFont());
StackPane pane = new StackPane(t);
pane.layout();
double height = t.getLayoutBounds().getHeight();
double padding = 20 ;
textArea.setMinHeight(height+padding);
});
I am trying to insert an image into table view in JavafX. Here is how I set up my table view:
TableColumn prodImageCol = new TableColumn("IMAGES");
prodImageCol.setCellValueFactory(new PropertyValueFactory<Product, Image>("prodImage"));
prodImageCol.setMinWidth(100);
// setting cell factory for product image
prodImageCol.setCellFactory(new Callback<TableColumn<Product,Image>,TableCell<Product,Image>>(){
#Override
public TableCell<Product,Image> call(TableColumn<Product,Image> param) {
TableCell<Product,Image> cell = new TableCell<Product,Image>(){
public void updateItem(Product item, boolean empty) {
if(item!=null){
ImageView imageview = new ImageView();
imageview.setFitHeight(50);
imageview.setFitWidth(50);
imageview.setImage(new Image(product.getImage()));
}
}
};
return cell;
}
});
viewProduct.setEditable(false);
viewProduct.getColumns().addAll(prodImageCol, prodIDCol, prodNameCol, prodDescCol, prodPriceCol, col_action);
viewProduct.getItems().setAll(product.populateProductTable(category));
private SimpleObjectProperty prodImage;
public void setprodImage(Image value) {
prodImageProperty().set(value);
}
public Object getprodImage() {
return prodImageProperty().get();
}
public SimpleObjectProperty prodImageProperty() {
if (prodImage == null) {
prodImage = new SimpleObjectProperty(this, "prodImage");
}
return prodImage;
}
And this is how I retrieve the image from database:
Blob blob = rs.getBlob("productImage");
byte[] data = blob.getBytes(1, (int) blob.length());
bufferedImg = ImageIO.read(new ByteArrayInputStream(data));
image = SwingFXUtils.toFXImage(bufferedImg, null);
However I am getting error at the setting up of table view: imageview.setImage(new Image(product.getImage()));
The error message as:
no suitable constructor found for Image(Image)
constructor Image.Image(String,InputStream,double,double,boolean,boolean,boolean) is not applicable
(actual and formal argument lists differ in length)
constructor Image.Image(int,int) is not applicable
(actual and formal argument lists differ in length)
constructor Image.Image(InputStream,double,double,boolean,boolean) is not applicable
(actual and formal argument lists differ in length)
constructor Image.Image(InputStream) is not applicable
(actual argument Image cannot be converted to InputStream by method invocation conversion)
constructor Image.Image(String,double,double,boolean,boolean,boolean) is not applicable
(actual and formal argument lists differ in length)
constructor Image.Image(String,double,double,boolean,boolean) is not applicab...
I did managed to retrieve and display an image inside an image view but however, I can't display it in table column. Any help would be appreciated. Thanks in advance.
The problem that's causing the exception is that your method product.getImage() is returning an javafx.scene.Image. There's no need to do anything else at this point: You have an image, so use it (before you were trying to construct new Image(Image) - which is not even possible). This is what you want to be using:
imageview.setImage(product.getImage());
Your second problem is that while you're creating an ImageView every time you update the cell, you're not doing anything with it. Here's your original code:
TableCell<Product,Image> cell = new TableCell<Product,Image>(){
public void updateItem(Product item, boolean empty) {
if(item!=null){
ImageView imageview = new ImageView();
imageview.setFitHeight(50);
imageview.setFitWidth(50);
imageview.setImage(new Image(product.getImage()));
}
}
};
return cell;
Like #tomsontom suggested, I'd recommend using setGraphic(Node) to attach your ImageView to the TableCell. So you might end up with something like this:
//Set up the ImageView
final ImageView imageview = new ImageView();
imageview.setFitHeight(50);
imageview.setFitWidth(50);
//Set up the Table
TableCell<Product,Image> cell = new TableCell<Product,Image>(){
public void updateItem(Product item, boolean empty) {
if(item!=null){
imageview.setImage(product.getImage()); //Change suggested earlier
}
}
};
// Attach the imageview to the cell
cell.setGraphic(imageview)
return cell;
The first point #tomsontom was making is that your method of creating an Image is a little roundabout. Sure, it seems to work... but there's a simpler way. Originally you were using:
bufferedImg = ImageIO.read(new ByteArrayInputStream(data));
image = SwingFXUtils.toFXImage(bufferedImg, null);
But a better way of doing it would be switching those lines with:
image = new Image(new ByteArrayInputStream(data));
why are not creating the Image directly from the data new Image(new ByteArrayInputStream(data)) no need to rewrap it our use Swing stuff
I don't see a public Image(Object) constructor in FX8 - why passing it anyways if you are already have an image instance?
you need to set the ImageView on the cell with setGraphic()
I am using LWUIT 1.5 tabs to show notifications. I have three Tabs and I fetch notifications from a php web service. I successfully fetched list of notifications for first Tab. But for next two Tabs I am failing to understand what code I should write to
Detect that second/third Tab is clicked. I know how to add commandListener to a Button. What commandListener is there for Tab selection?
How to refresh content of a Tab when new data is received from the server?
private void showNotificationList() {
try {
Form f = new Form("Notifications");
f.setScrollable(false);
f.setLayout(new BorderLayout());
final List list = new List(getNotifications()); //gets hashtables - notices
list.setRenderer(new GenericListCellRenderer(createGenericRendererContainer(), createGenericRendererContainer()));
list.setSmoothScrolling(true);
//System.out.println("adding list component to listview");
list.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
int i = list.getSelectedIndex();
noticeDetailsForm(notices[i]);
//Dialog. show( "title", notices[i].toString(), "ok", "exitt");
}
});
//Container c2 = new Container(new BoxLayout(BoxLayout.Y_AXIS));
//c2.addComponent(list);
Tabs tabs = new Tabs(Tabs.TOP);
tabs.addTab("Recent", list);
tabs.addTab("Urgent", new Label("urgent goes here"));
tabs.addTab("Favourites", new Label("favs goes here"));
//f.addComponent(tabs);
f.addComponent(BorderLayout.CENTER, tabs);
Command backComm = new Command("Back") {
public void actionPerformed(ActionEvent ev) {
Dashboard.dbInstance.setUpDashboard();
}
};
f.addCommand(backComm);
//System.out.println("showing lsit form");
f.show();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private Container createGenericRendererContainer() throws IOException { //System.out.println("container called");
//System.out.println("container called");
Container c = new Container(new BorderLayout());
c.setUIID("ListRenderer");
Label xname = new Label("");
Label description = new Label();
Label focus = new Label("");
Container cnt = new Container(new BoxLayout(BoxLayout.Y_AXIS));
xname.setName("Name");
xname.getStyle().setBgTransparency(0);
xname.getStyle().setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));
//description.setFocusable(true);
description.setName("Description");
cnt.addComponent(xname);
cnt.addComponent(description);
c.addComponent(BorderLayout.CENTER, cnt);
Button thumb = new Button(Image.createImage("/res/home-work.png"));
//Image img = Image.createImage("/res/home-work.png");
c.addComponent(BorderLayout.WEST, thumb);
return c;
}
private Hashtable[] getNotifications() {
int total = notices.length;
//System.out.println(total);
Hashtable[] data = new Hashtable[total];
//Hashtable[] data = new Hashtable[5];
/data[0] = new Hashtable();
data[0].put("Name", "Shai");
data[0].put("Surname", "Almog");
data[0].put("Selected", Boolean.TRUE);/
for (int i = 0; i < total; i++) {
data[i] = new Hashtable();
//System.out.println(notices[i].getName());
data[i].put("Name", notices[i].getName());
data[i].put("Description", notices[i].getDescription());
data[i].put("Id", Integer.toString(notices[i].getId()));
}
return data;
}
1)I had the same problem and I solved it by overriding Keyreleased of the Form not the Tab
and inside it I check for the component that is focused and if it is the Tab get "tab.selectedIndex" to detect in which Tab I am and load appropriate data .
Here is Sample code(this inside the my derived form that extends Form )
**
public void keyReleased(int keyCode) {
Component p=this.getFocused();
String str= p.getClass().getName();
if(str.toLowerCase().indexOf("radiobutton")!=-1){ // Radiobutton because when u
Here do tab specific work focus on the
tab it returns radiobutton.
lwuit understands tabs as list
of radiobuttons
}**
2)and about refreshing the data I did a solution and I don't Know if its right
I get the new data , create new List and remove the old one and attach the new one then
call Form.repaint();