Given the following code:
chart = new Chart2D();
trace = new Trace2DSimple();
trace.setTracePainter(new TracePainterVerticalBar(chart));
chart.addTrace(trace);
// default tracepainter color is Black
TracePoint2D first = new TracePoint2D(0, 1 );
TracePoint2D second = new TracePoint2D(1, 10 );
TracePoint2D third = new TracePoint2D(2, 20 );
PointPainterVerticalBar red = new PointPainterVerticalBar(10,chart);
red.setColor(Color.red);
PointPainterVerticalBar green = new PointPainterVerticalBar(10,chart);
green.setColor(Color.green);
PointPainterVerticalBar blue = new PointPainterVerticalBar(10,chart);
blue.setColor(Color.blue);
first.addAdditionalPointPainter(red);
second.addAdditionalPointPainter(green);
third.addAdditionalPointPainter(blue);
trace.addPoint(first);
trace.addPoint(second);
trace.addPoint(third);
As you can see I am trying to get three different TracePoints with different colors onto the chart but somehow they all remain black. Any Ideas ?
Well it is perfectly possible just implement you own Trace- and PointPainter.
Within the new TracePainter tell it to use your new PointPainter:
public TracePainterBlank(final int barWidth, final Chart2D chart) {
this.m_pointPainter = new PointPainterBlank(barWidth, chart);
}
Then within the PointPainer be explicit about the color which you set with tracepainter.setColor(Color.whatever) and apply it to the actual graphics:
public void paintPoint(final int absoluteX, final int absoluteY, final int nextX,
final int nextY, final Graphics g, final ITracePoint2D original) {
g.setColor(this.getColor());
g.fillRect(absoluteX - this.m_halfWidth, absoluteY, 2 * this.m_halfWidth, this.m_chart
.getYChartStart()
- absoluteY);
}
That lets you color each TracePoint separately.
I think with jChart2D you can only set Color for a "trace" and not colors of individual points.
your code is buggy as you set the color only on red three times.
But as it remains black as you write I fear there is a bug (that code was changed recently). So consider posting a bug at sourceforge if it is the case.
HTH,
Achim
Related
I want to get the color for specific coordinates inside a Canvas. I already tried getting a snapshot using this code:
WritableImage snap = gc.getCanvas().snapshot(null, null);
snap.getPixelReader().getArgb(x, y); //This just gets the color without assigning it.
But it just takes too much time for my application. I was wondering if there is any other way to access the color of a pixel for which I know the coordinates.
A Canvas buffers the drawing instructions prescribed by invoking the methods of a GraphicsContext. There are no pixels to read until the Canvas is rendered in a later pulse, and the internal format of the instruction buffer is not exposed in the API.
If a snapshot() of the Canvas is feasible, a rendered pixel may be examined using the resulting image's PixelReader.
int aRGB = image.getPixelReader().getArgb(x, y);
This example focuses on a single pixel. This example displays the ARGB BlendMode result in a TextField and a Tooltip as the mouse moves on the Canvas. More examples may be found here.
As an alternative, consider drawing into a BufferedImage, illustrated here, which allows access to the image's pixels directly and via its WritableRaster. Adding the following line to this complete example outputs the expected value for opaque red in ARGB order: ffff0000.
System.out.println(Integer.toHexString(bi.getRGB(50, 550)));
public class Pixel
{
private static final SnapshotParameters SP = new SnapshotParameters();
private static final WritableImage WI = new WritableImage(1, 1);
private static final PixelReader PR = WI.getPixelReader();
private Pixel()
{
}
public static int getArgb(Node n, double x, double y)
{
synchronized (WI)
{
Rectangle2D r = new Rectangle2D(x, y, 1, 1);
SP.setViewport(r);
n.snapshot(SP, WI);
return PR.getArgb(0, 0);
}
}
public static Color getColor(Node n, double x, double y)
{
synchronized (WI)
{
Rectangle2D r = new Rectangle2D(x, y, 1, 1);
SP.setViewport(r);
n.snapshot(SP, WI);
return PR.getColor(0, 0);
}
}
}
I created a design in blender exported to STL and used the StlModelImporterJFX to import it into my JavaFX program and run it. Everything runs fine, the application works, there is just one thing missing...texture, so basically, I want to take my imported mesh and create an image as seen below for a smaller design.
Is there any program or algorithm that I can use to create an image such as that below that I can later edit manually and use as a texture for the entire Triangle Mesh? Also on a side note is it possible to edit this image live in the program and swap out colours while running? Sorry if this is poorly worded, if you want any clarification, I can provide it.
When you import a 3D model with a third-party 3D importer you have less control of the resulting TriangleMesh. If you want to provide texture features to your model you'll have to edit the exported file and add the texture coordinates, which is not the best approach.
But if you could generate the mesh from scratch, you could easily apply textures over it.
This question shows how you can define the texture coordinates and uses the same net image you have to provide the texture of an icosahedron.
Based on the answer on that question, the texture can be defined without an actual image, just with a palette of colors.
And you can easily change those on runtime, i.e. when you click on one face you can change the color on that face.
The Fxyz library makes use of a TexturedMesh, designed to easily apply textures to 3D shapes.
You can find many primitives there, like the icosahedron.
This question shows the result of different texture modes over an icosahedron.
This short snippet shows how you can apply a texture over faces, and change it on runtime:
private int numColors = 10;
#Override
public void start(Stage primaryStage) {
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setTranslateZ(-5);
IcosahedronMesh icoFaces = new IcosahedronMesh(100, 0);
icoFaces.setTextureModeFaces(numColors);
icoFaces.getTransforms().addAll(new Rotate(20, Rotate.X_AXIS), new Rotate(-10, Rotate.Y_AXIS));
final Group group = new Group(icoFaces);
Scene scene = new Scene(group, 600, 400, true, SceneAntialiasing.BALANCED);
scene.setCamera(camera);
primaryStage.setScene(scene);
primaryStage.setTitle(("Icosahedron - FXyz3D"));
primaryStage.show();
icoFaces.setOnMouseClicked(e -> {
ObservableFaceArray faces = ((TriangleMesh) icoFaces.getMesh()).getFaces();
int selectedFace = e.getPickResult().getIntersectedFace();
int colorId = faces.get(6 * selectedFace + 1);
int newColorId = colorId + 1 >= numColors ? 0 : colorId + 1;
faces.set(6 * selectedFace + 1, newColorId);
faces.set(6 * selectedFace + 3, newColorId);
faces.set(6 * selectedFace + 5, newColorId);
});
}
Running the application:
And after clicking in the frontal green face:
I can change the color of the font like this
LabelStyle style1 = new LabelStyle(..some font...,
Color.valueOf("FF4500")
);
label.setStyle(style1);
but how do I change the background?
right now the background is the same as the background of whole screen which is set in
render method lke this
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(
1.000f, 0.980f, 0.941f
,1);
Label label = new Label(labelText, skin);
Pixmap labelColor = new Pixmap(labelWidth, labelHeight, Pixmap.Format.RGB888);
labelColor.setColor(<your-color-goes-here>);
labelColor.fill();
label.getStyle().background = new Image(new Texture(labelColor)).getDrawable();
Basically, use the getDrawable() function of the Image class to assign the color of your Label's LabelStyles' background Drawable.
This is the simplest workaround I've been able to come up with and, frankly, it's just silly that there is no setBackground() in the Label class.
Actually, maybe the easiest fix is to hack the Label class and add a setBackground() method to it.
[Edit] Be sure to dispose of Pixmaps when you are done with them; i.e. labelColor.dispose();
[Update] #Mitrakov Artem made a good point: The above solution will affect all instances of this LabelStyle. If that's not what you want you can create a new LabelStyle, use the above method on it, then save it to the Label. Quoting Artem: "So I would recommend to create a new style (LabelStyle style = new LabelStyle(label.getStyle());), change its background and then apply it to the label (label.setStyle(style);)"
Actually you do not change the background of the Lable like that. You did just change the clearcolour. Guess you know that.
To change the background you need to change the background at the style of the label. To do so i'd recommend to use a simple NinePatch as background, (can be a square! if its white you can change the colour of the ninepatch and the background colour changes!)
NinePatch temp = new NinePatch(new Texture(....), 10, 10, 10, 10); //edges
For more information about ninepatch take a look here libgdx wiki ninepatch
You need to add that ninepatch to an Skin objekt. For example like this
Skin skin = new Skin();
skin.add("background",temp)
After that you can get a drawable from the skin that you can set as background of the LabelStyle.
style1.background = skin.getDrawable("background");
see libgdx API LabelStyle
You can also use a simple bitmap but that does get scaled to the label size which causes in most of the cases deformation. A Ninepatch can be scaled without having deformation.
If you need a quick and easy solution, you can use the snippet below. It doesn't work well with multiline text because it doesn't take the text width per line into account.
Anyway, the background is automatically adjusted to the width and height of the label widget (i.e. if your text changes).
private Label label = new Label("text", createLabelStyleWithBackground());
private LabelStyle createLabelStyleWithBackground() {
LabelStyle labelStyle = new LabelStyle();
labelStyle.font = new BitmapFont();
labelStyle.fontColor = Color.WHITE;
labelStyle.background = createBackground();
return labelStyle;
}
private Drawable createBackground() {
Pixmap labelColor = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
Color color = new Color(Color.GRAY);
color.a = 0.75f;
labelColor.setColor(color);
labelColor.fill();
Texture texture = new Texture(labelColor);
return new BaseDrawable() {
#Override
public void draw(Batch batch, float x, float y, float width, float height) {
GlyphLayout layout = label.getGlyphLayout();
x = label.getX();
y = label.getY() - (layout.height + 15) / 2; // +15 is some space
batch.draw(texture, x, y, layout.width, layout.height + 15);
}
};
}
here is an example with a multiline label
I'm having a problem with this implementation:
if(blueActive) {
blueFormat = new LineAndPointFormatter(Color.rgb(0,0,255), null, null);
blue = new SimpleXYSeries(xArray,yArray, selectedDate);
Log.e(TAG , "blueActive");
cvPlot.addSeries(blue, blueFormat);
}
if(redActive) {
redFormat = new LineAndPointFormatter(Color.rgb(255,0,0), null, null);
red = new SimpleXYSeries(xArray,yArray, selectedDate);
Log.e(TAG , "redActive");
cvPlot.addSeries(red, redFormat);
}
if(greenActive) {
greenFormat = new LineAndPointFormatter(Color.rgb(0,255,0), null, null);
green = new SimpleXYSeries(xArray,yArray, selectedDate);
Log.e(TAG , "greenActive");
cvPlot.addSeries(green, greenFormat);
}
cvPlot.redraw();
The series are plotted with the correct xArray and yArray, but when the graph redraws, all the plots are the same color. I'm looking for this code to redraw the plot with three different colors. Am I doing something logically wrong here?
Although this question wasn't very descriptive with the other code involved, ultimately the answer was to add this into the onClick that started the process of adding the plots:
xArray.clear();
yArray.clear();
The lines were overlapping, and when the next color was added, since the red plot was selected after blue, the two arrays grew to include the points of the blue and red, making it look like the color wasn't changing. In other words, the red array included the blue array, and since those points were identical to the blue plot, I couldn't see the blue plot since the red plot was on top!
I had set up a Log.d long before this problem but really didn't notice the array doubling since I didn't log the count because I only wanted to see that the x and y values were populating.
Log your array counts and clear your arrays rook dawg!!
I have a certain text, that i want to annotate for the user. Unfortunately i don't even see where to begin. My algorithm gives as output a range on a string. What i am going for is something like this:
I would need two ways to marker the Characters ( Blue line, red line), maybe also to invert the character (Give a character a different background), or make them fat. What is especially difficult is aligning the Pictures (here designated by two black dots) with the characters. Since the characters should be in Courier New, i could know where to put the offset, but i cannot seem to do it.
Lastly i would have to apply a break after X characters and begin a new line, just like in the picture. I have not found any example how to approach this with java yet. With python i could use ImageDraw, but i am out of the water with java.
is it possible to show this in a canvas on the screen and export this as svg or pdf? I dont know any libraries that could do this. So i would be happy to receive some suggestions/examples also along this way.
The key is to deal with the FontMetrics API. The best you can do is looking at this reference doc.
Here is a sample code demonstrating this usage. It draws red and blue lines around an "Hello world" text according a range of chars.
The text is inside a JLabel, but you can adapt the paint method on any component (but you will have to call graphics.drawChars to paint the text.)
(the code is not very nice, but it demonstrates the usage of FontMetrics)
package com.example.swing;
import javax.swing.*;
import java.awt.*;
public class DemoFontMetrics {
public static void main(String[] args){
JFrame frame = new JFrame();
DecoratedLabel label = new DecoratedLabel("hello world !",new int[]{2,4}, new int[]{6,9});
JPanel textContainer = new JPanel(new FlowLayout());
textContainer.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
textContainer.add(label);
frame.getContentPane().add(textContainer);
frame.pack();
frame.setVisible(true);
}
private static class DecoratedLabel extends JLabel{
int startBlue;
int endBlue;
int startRed;
int endRed;
private DecoratedLabel(String text, int[] blueRange, int[] redRange) {
super(text);
startBlue = blueRange[0];
endBlue = blueRange[1];
startRed = redRange[0];
endRed = redRange[1];
}
#Override
public void paint(Graphics g) {
super.paint(g); //draw text
//set line with : 3
Stroke stroke = new BasicStroke(3f);
((Graphics2D)g).setStroke(stroke);
FontMetrics fm = g.getFontMetrics();
int h = fm.getHeight();
//compute blue line coordonate
fm.stringWidth(getText().substring(0,startBlue));
int x1 = fm.stringWidth(getText().substring(0, startBlue));
int x2 = fm.stringWidth(getText().substring(0, endBlue));
g.setColor(Color.BLUE);
g.drawLine(x1,0,x2,0);// draw blue line
//compute red line coordonates
int x3 = fm.stringWidth(getText().substring(0,startRed));
int x4 = fm.stringWidth(getText().substring(0, endRed));
g.setColor(Color.RED);
g.drawLine(x3,h-1,x4,h-1); // draw redline
}
}
}
If the text is displayed via JTextPane you can conveniently define a custom HighlightPainter, that draws lines above or under the text.
Then you can add highlights to the text pane programmatically by calling:
textPane.getHighlighter().addHighlight(startPos, endPos,
myLineHighlightPainter);
Images may as well easily be added to the pane, by:
textPane.setIcon(myImageIcon);
You can create svg directly for example: http://xmlgraphics.apache.org/batik/ it's an xml based vector graphics format.
EDIT: You can display svg in java, you can create pdf's with it from java. You can publish it in the web (simply as svg).