I have as some problem with using JGraph(T) library.
I need change default selection view, example: default background is orange color, if vertex selected then green border was added, can i change this visualization strategy to change background to Color.BLUE on selected element.
I try execute follow code:
GraphSelectionModel graphSelectionModel = new DefaultGraphSelectionModel(jGraph);
graphSelectionModel.setSelectionMode(GraphSelectionModel.MULTIPLE_GRAPH_SELECTION);
graphSelectionModel.addGraphSelectionListener(new GraphSelectionListener()
{
HashMap oldestCellsAndAttrs = new HashMap();
#Override
public void valueChanged(GraphSelectionEvent e)
{
jGraph.getModel().beginUpdate();
m_jgAdapter.edit(oldestCellsAndAttrs, null, null, null);
oldestCellsAndAttrs.clear();
Map cellAndAttrs = new HashMap();
for (Object obj : e.getCells())
{
DefaultGraphCell cell = (DefaultGraphCell) obj;
oldestCellsAndAttrs.put(cell, JGraphModelAdapter.createDefaultVertexAttributes());
Map attrs = cell.getAttributes();
GraphConstants.setBackground(attrs, Color.BLUE);
cellAndAttrs.put(cell, attrs);
}
m_jgAdapter.edit(cellAndAttrs, null, null, null);
jGraph.getModel().endUpdate();
}
});
fillGraph(tree, g);
layout(g, m_jgAdapter, jGraph);
setSize(3 * width / 4, height);
jGraph.setSelectionModel(graphSelectionModel);
This change bkg on same selected objs, but not return after non-selection.
Is exists default solve for this problem ?
I solve problem with foollowing code:
#Override
public void valueChanged(GraphSelectionEvent e)
{
Object[] cells = e.getCells();
HashMap<DefaultGraphCell, AttributeMap> cellsAndAttrs = new HashMap<DefaultGraphCell, AttributeMap>();
for (Object c : cells)
{
DefaultGraphCell cell = (DefaultGraphCell) c;
AttributeMap cellAttrs = cell.getAttributes();
if (jGraph.isCellSelected(cell))
GraphConstants.setBackground(cellAttrs, SELECTED_COLOR);
else
GraphConstants.setBackground(cellAttrs, NON_SELECTED_COLOR);
cellsAndAttrs.put(cell, cellAttrs);
}
m_jgAdapter.edit(cellsAndAttrs, null, null, null);
}
Related
I'm making a chat application using JavaFX for the GUI. I display the chat content in a ListView, but I have one big problem - it's very very slow. When I add new items to the list and especially when I scroll the list up/down. I think maybe it has something to do with the fact that the list refreshes itsellf every time a new item is added (each cell in the list!) and also refreshes every time I scroll up/down.
Does someone know what can I do to solve this problem? TNX
I override ListCell's updateItem:
chatListView.setCellFactory(new Callback<ListView<UserInfo>, ListCell<UserInfo>>() {
#Override
public ListCell<UserInfo> call(ListView<UserInfo> p) {
ListCell<UserInfo> cell = new ListCell<UserInfo>() {
#Override
protected void updateItem(UserInfo item, boolean bln) {
super.updateItem(item, bln);
if (item != null) {
BorderPane borderPane = new BorderPane();
ImageView profileImage = new ImageView(new Image(item.getImageURL()));
profileImage.setFitHeight(32);
profileImage.setFitWidth(32);
Rectangle clip = new Rectangle(
profileImage.getFitWidth(), profileImage.getFitHeight()
);
clip.setArcWidth(30);
clip.setArcHeight(30);
profileImage.setClip(clip);
SnapshotParameters parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);
WritableImage image = profileImage.snapshot(parameters, null);
profileImage.setClip(null);
profileImage.setImage(image);
ImageView arrowImage = new ImageView(new Image("arrow1.png"));
ImageView arrowImage2 = new ImageView(new Image("arrow1.png"));
Label nameLabel = new Label(item.getUserName());
nameLabel.setStyle(" -fx-text-alignment: center; -fx-padding: 2;");
HBox hbox = null;
Label textLabel = new Label();
String messageText = splitTolines(item.getMessage());
textLabel.setText(messageText);
textLabel.setStyle("-fx-background-color: #a1f2cd; "
+ "-fx-padding: 10;\n"
+ "-fx-spacing: 5;");
hbox = new HBox(arrowImage, textLabel);
VBox vbox = new VBox(profileImage, nameLabel);
BorderPane.setMargin(vbox, new Insets(0, 10, 10, 10));
BorderPane.setMargin(hbox, new Insets(10, 0, 0, 0));
//Time
Date dNow = new Date();
SimpleDateFormat ft = new SimpleDateFormat("hh:mm a");
Label timeLabel = new Label(ft.format(dNow));
timeLabel.setStyle("-fx-font: 8px Tahoma; -fx-width: 100%");
HBox hbox2 = new HBox(arrowImage2, timeLabel);
arrowImage2.setVisible(false);
VBox vbox2 = new VBox(hbox, hbox2);
borderPane.setCenter(vbox2);
borderPane.setLeft(vbox);
setGraphic(borderPane);
}
}
};
return cell;
}
});
Never ever add (big) GUI Elements in updateItem() without checking if it is not already there.
updateItem() is called everytime for EVERY SINGLE ROW when you scroll, resize or change gui in any other way.
You should alway reset the graphic to null if you do not have an item or the second boolean of updateItem(item, empty) is false, because the second boolean is the EMPTY flag.
I recommend to you that you use a VBox instead of a ListView.
You must not build new instances of your components everytime the view gets updated.
Instanciate them one time initialy, then you reuse and change their attributes.
I just noticed that too. It's too slow even for a list containing only 5-10 items (with scaled images and text). Since I need no selection feature, I also rewrote the code to use VBox instead and the slowness is immediately gone!
To emulate the setItems, I have a helper function which you may find handy:
public static <S, T> void mapByValue(
ObservableList<S> sourceList,
ObservableList<T> targetList,
Function<S, T> mapper)
{
Objects.requireNonNull(sourceList);
Objects.requireNonNull(targetList);
Objects.requireNonNull(mapper);
targetList.clear();
Map<S, T> sourceToTargetMap = new HashMap<>();
// Populate targetList by sourceList and mapper
for (S s : sourceList)
{
T t = mapper.apply(s);
targetList.add(t);
sourceToTargetMap.put(s, t);
}
// Listen to changes in sourceList and update targetList accordingly
ListChangeListener<S> sourceListener = new ListChangeListener<S>()
{
#Override
public void onChanged(ListChangeListener.Change<? extends S> c)
{
while (c.next())
{
if (c.wasPermutated())
{
for (int i = c.getFrom(); i < c.getTo(); i++)
{
int j = c.getPermutation(i);
S s = sourceList.get(j);
T t = sourceToTargetMap.get2(s);
targetList.set(i, t);
}
}
else
{
for (S s : c.getRemoved())
{
T t = sourceToTargetMap.get2(s);
targetList.remove2(t);
sourceToTargetMap.remove2(s);
}
int i = c.getFrom();
for (S s : c.getAddedSubList())
{
T t = mapper.apply(s);
targetList.add(i, t);
sourceToTargetMap.put(s, t);
i += 1;
}
}
}
}
};
sourceList.addListener(new WeakListChangeListener<>(sourceListener));
// Store the listener in targetList to prevent GC
// The listener should be active as long as targetList exists
targetList.addListener((InvalidationListener) iv ->
{
Object[] refs = { sourceListener, };
Objects.requireNonNull(refs);
});
}
It can then be used like:
ObservableList<Bookmark> bookmarkList;
VBox bookmarkListVBox;
mapByValue(bookmarkList, bookmarkListVBox.getChildren(), bmk -> new Label(bmk.getName());
To automatically update the list (VBox's children) from observable list.
PS: other functions such as grouping are here => ObservableListHelper
I use a StyledCellLabelProvider to format text string as 'Hyperlink'.
// Column for the link
TableViewerColumn col2 = createTableViewerColumn("Link", 100, 1, viewer);
col2.setLabelProvider(new StyledCellLabelProvider() {
#Override
public void update(ViewerCell cell)
{
Object element = cell.getElement();
if(element instanceof Person)
{
Person person = (Person) cell.getElement();
/* make text look like a link */
StyledString text = new StyledString();
StyleRange myStyledRange = new StyleRange(0, person.getLocation().length(), Display.getCurrent().getSystemColor(SWT.COLOR_BLUE), null);
myStyledRange.underline = true;
text.append(person.getLocation(), StyledString.DECORATIONS_STYLER);
cell.setText(text.toString());
StyleRange[] range = { myStyledRange };
cell.setStyleRanges(range);
super.update(cell);
}
}
});
I also set text align of TableViewerColumn is CENTER but after using this style the text is left align.
How can I set CENTER align of text and change the cursor into link cursor when touch to the text?
Thanks
I couldn't find an answer in the manual, or on SO. I want to make a graph with JGraphX that displays some verices and edges, but I don't want the user to be able to move anything around, nor for those green edit boxes to appear on the vortexes or edges. It's just for display only.
I tried this modification of the "Hello World" example to no avail. Any suggestions?
package com.mxgraph.examples.swing;
import java.util.Hashtable;
import javax.swing.JFrame;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxConstants;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxStylesheet;
public class HelloWorld extends JFrame
{
/**
*
*/
private static final long serialVersionUID = -2707712944901661771L;
public HelloWorld()
{
super("Hello, World!");
mxGraph graph = new mxGraph();
Object parent = graph.getDefaultParent();
//my addition of a stylesheet, I used it on the first node to see if it mad
//a difference, it didn't regarding dragability//////////////////////////////
mxStylesheet stylesheet = graph.getStylesheet();
Hashtable<String, Object> style = new Hashtable<String, Object>();
style.put(mxConstants.STYLE_SHAPE, mxConstants.SHAPE_ELLIPSE);
style.put(mxConstants.STYLE_OPACITY, 50);
style.put(mxConstants.STYLE_FONTCOLOR, "#774400");
style.put(mxConstants.STYLE_EDITABLE, false);
stylesheet.putCellStyle("ROUNDED", style);
//tried this too///////////////////////////////////////////////
graph.setCellsEditable(false);
graph.getModel().beginUpdate();
try
{
Object v1 = graph.insertVertex(parent, null, "Hello", 20, 20, 80,
30, "ROUNDED");
Object v2 = graph.insertVertex(parent, null, "World!", 240, 150,
80, 30);
graph.insertEdge(parent, null, "Edge", v1, v2);
}
finally
{
graph.getModel().endUpdate();
}
mxGraphComponent graphComponent = new mxGraphComponent(graph);
getContentPane().add(graphComponent);
}
public static void main(String[] args)
{
HelloWorld frame = new HelloWorld();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 320);
frame.setVisible(true);
}
}
You can disable the whole graph component mxGraphComponent:
graphComponent.setEnabled(false);
You could override isCellSelectable to prevent cell selection
mxGraph graph = new mxGraph() {
#Override
public boolean isCellSelectable(Object cell) {
if (cell != null) {
if (cell instanceof mxCell) {
mxCell myCell = (mxCell) cell;
if (myCell.isEdge())
return false;
}
}
return super.isCellSelectable(cell);
}
};
I have created a custom button using this code:
Button goButton = (Button) findViewById(R.id.buttonStartTest);
View v = findViewById(R.id.buttonStartTest);
v.setBackground( new DrawableGradient(new int[] { btnColor,btnColor, 0xffffffff }, 110,10));
goButton.setText(getString(R.string.START_FORM));
And where the DrawableGradent looks like:
public class DrawableGradient extends GradientDrawable {
DrawableGradient(int[] colors, int cornerRadius,int strokeSize) {
super(Orientation.BOTTOM_TOP, colors);
try {
this.setShape(GradientDrawable.RECTANGLE);
this.setGradientType(GradientDrawable.LINEAR_GRADIENT);
this.setCornerRadius(cornerRadius);
int strokeColor = Color.argb(50, 0, 0, 0);
this.setStroke(strokeSize,strokeColor);
} catch (Exception e) {
e.printStackTrace();
}
}
}
This results in a button that looks like this:
This is what I want to get except that I want the stroke to only be on the outside of the button. How can I achieve this?
This is what the desired look is:
Thanks for your help! :)
/Daniel
How to add Hyperlink in SWT Table column ?
I`m using org.eclipse.swt.widgets.Table class.
Is there any way to do this without using TableViewer, JFace ?
I tried this way but not working correctly (not showing hyperlinks).
for(int i=2; i<4; i++){
Hyperlink link = new Hyperlink(table, SWT.WRAP);
link.setText(temp[i]);
link.setUnderlined(true);
TableEditor editor = new TableEditor(table);
editor.setEditor(link, tableItem[index-1], i); //set hyperlinks in column i
}
Below is one way to draw the hyperlink using TableView with a LabelProvider, as mentioned in Tonny Madsen's answer.
The code below just paints the hyperlink.
TableViewerColumn column = ...
column.setLabelProvider( new MyHyperlinkLabelProvider( tableViewerFiles.getTable() ));
private final class MyHyperlinkLabelProvider extends StyledCellLabelProvider {
MyHyperlink m_control;
private MyHyperlinkLabelProvider( Composite parent ) {
m_control = new MyHyperlink( parent, SWT.WRAP );
}
#Override
protected void paint( Event event, Object element ) {
String sValue = ... [Get cell value from row element]
m_control.setText( sValue );
GC gc = event.gc;
Rectangle cellRect = new Rectangle( event.x, event.y, event.width, event.height );
cellRect.width = 4000;
m_control.paintText( gc, cellRect);
}
}
private class MyHyperlink extends Hyperlink {
public MyHyperlink(Composite parent, int style) {
super(parent, style);
this.setUnderlined(true);
}
#Override
public void paintText(GC gc, Rectangle bounds) {
super.paintText(gc, bounds);
}
}
Yes, that is certainly possible. To do this you have to implement SWT.ItemPaint (and possibly also SWT.ItemErase and SWT.ItemMeassure).
It is easier with TableView though if you use the correct LabelProvider...
You need to set the size of the editor:
editor.grabHorizontal = true;
//or
editor.minimumWidth = 50;