JfreeChart : changing axis line angle on polar chart - java

Since a picture is worth a thousand words, I'll show you.
This is what I have:
This is what I need:
Some code maybe useful:
private JFreeChart createChart (XYDataset dataset)
{
ValueAxis radiusAxis = new NumberAxis ();
radiusAxis.setTickLabelsVisible (false);
// Rendering serie ( handeling null values )
DefaultPolarItemRenderer ren = new DefaultPolarItemRenderer ()
{
#Override
public void drawSeries (Graphics2D g2, Rectangle2D dataArea,
PlotRenderingInfo info, PolarPlot plot, XYDataset dataset, int seriesIndex)
{
boolean newPath = true;
GeneralPath polyline = new GeneralPath ();
int numPoints = dataset.getItemCount (seriesIndex);
for (int i = 0 ; i < numPoints - 1 ; i++)
{
double theta = dataset.getXValue (seriesIndex, i);
double radius = dataset.getYValue (seriesIndex, i);
Point p = plot.translateValueThetaRadiusToJava2D (theta, radius,
dataArea);
if (p.x == 0 && p.y == 0)
{
newPath = true;
}
else
{
if (newPath)
{
polyline.moveTo (p.x, p.y);
newPath = false;
}
else
{
polyline.lineTo (p.x, p.y);
}
}
}
g2.setPaint (lookupSeriesPaint (seriesIndex));
g2.setStroke (lookupSeriesStroke (seriesIndex));
g2.draw (polyline);
}
};
// removing fill serie
ren.setSeriesFilled (0, false);
// custimizing angles
PolarPlot plot = new PolarPlot (dataset, radiusAxis, ren)
{
#Override
protected java.util.List refreshAngleTicks ()
{
java.util.List ticks = new ArrayList ();
ticks.add (new NumberTick (0, "12AM", TextAnchor.CENTER, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (30, "2AM", TextAnchor.TOP_LEFT, TextAnchor.TOP_RIGHT, 0));
ticks.add (new NumberTick (60, "4AM", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (90, "6AM", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (120, "8AM", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (150, "10AM", TextAnchor.TOP_LEFT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (180, "12PM", TextAnchor.CENTER, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (210, "2PM", TextAnchor.TOP_RIGHT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (240, "4PM", TextAnchor.TOP_RIGHT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (270, "6PM", TextAnchor.TOP_RIGHT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (300, "8PM", TextAnchor.TOP_RIGHT, TextAnchor.TOP_LEFT, 0));
ticks.add (new NumberTick (330, "10PM", TextAnchor.TOP_RIGHT, TextAnchor.TOP_LEFT, 0));
return ticks;
}
};
// colors..
plot.setOutlinePaint (new Color (0, 0, 0, 0));
plot.setBackgroundPaint (Color.white);
plot.setRadiusGridlinePaint (Color.gray);
ren.setShapesVisible (true);
plot.setRadiusGridlinesVisible (true);
plot.setAngleGridlinesVisible (true);
plot.setAngleLabelsVisible (true);
plot.setOutlineVisible (true);
plot.setAngleGridlinePaint (Color.BLACK);
plot.setRenderer (ren);
JFreeChart chart = new JFreeChart ("", JFreeChart.DEFAULT_TITLE_FONT, plot, false);
chart.setBackgroundPaint (Color.white);
chart.setBorderVisible (false);
chart.setBorderPaint (Color.RED);
// showing Label Axis ( 0 ... 20 ... 30 ...40)
NumberAxis rangeAxis = (NumberAxis) plot.getAxis ();
rangeAxis.setTickLabelsVisible (true);
rangeAxis.setAxisLinePaint (Color.RED);
return chart;
}
As you can see, I want to change Axis Line angle; I don't know how to proceed.
Thank you.

You don't mention the used version of JFreeChart but JFreeChart 1.0.14 got some improvements for polarcharts. You can set an angle-offset via PolarPlot.setAngleOffset() which allows to start with 12am at whatever position you like.
However, the axes themselves cannot be at arbitrary angles but only at north, east, south or west. This can be set using PolarPlot.setAxisLocation().
hth,
- martin

Related

How to draw both graphics and buttons properly in Jframe?

I am having a hard time figuring out how to set up both graphics and buttons at thee same time without the buttons flickering.
I am trying to make a navigation program for my robot. I tried to add buttons to my program for the last week or two and nothing works out for me, thanks in advance!
Here is my code:
public static void main (String [] args) throws IOException{
image = ImageIO.read(new File("images/2020.jpg"));
double ratio = (double) image.getHeight() / (double) image.getWidth();
double Yscaled = (int) (Xscaled*ratio);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize((int) Xscaled+15 + 2*ButtonSpace + ButtonWidth,(int) Yscaled+34);
JButton clear = new JButton("Clear");
clear.setBounds((int)Xscaled+ButtonSpace, (int)Yscaled/4 - ButtonHeight/2, ButtonWidth, ButtonHeight);
window.add(clear);
cordList.add((int) Xs);
cordList.add((int) Ys);
JPanel painting = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
y1 = Math.sin(Math.toRadians(a))*c;
x1 = Math.cos(Math.toRadians(a))*c;
y2 = -Math.cos(Math.toRadians(a))*h;
x2 = -Math.sin(Math.toRadians(a))*h;
g.drawImage(image, 0, 0, (int) Xscaled, (int) Yscaled, null);
if (cordList.size() > 0){
if (cordList.get(cordList.size()-2) > Xscaled || cordList.get(cordList.size()-1) > Yscaled){
cordList.remove(cordList.size()-2);
cordList.remove(cordList.size()-1);
}
}
for (int i = 0; i < cordList.size(); i+=2){
int size = 5;
g.setColor(new Color(220, 242, 19));
g.fillOval(cordList.get(i)-size/2, cordList.get(i+1)-size/2, size, size);
g.setColor(new Color(0, 0, 0));
g.drawOval(cordList.get(i)-size/2, cordList.get(i+1)-size/2, size, size);
if(i < cordList.size()-2){
g.drawLine(cordList.get(i), cordList.get(i+1), cordList.get(i+2), cordList.get(i+3));
}
}
Triangle_Shape triangleShape = new Triangle_Shape(new Point2D.Double(Xs - x1, Ys - y1),
new Point2D.Double(Xs + x1, Ys + y1), new Point2D.Double(Xs - x2, Ys + y2));
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(triangleShape);
g2.setColor(new Color(19, 191, 15));
g2.fill(triangleShape);
repaint();
}
};
painting.setBounds(0, 0 ,(int) Xscaled ,(int) Yscaled);
window.add(painting);
window.getContentPane().addMouseListener(new Field());
window.setVisible(true);
}
I had the same problem a few years ago. JPanels can be pretty helpful, but drawing on your JFrame and adding buttons without flickering only works with JLabels for some reason. Just try replacing the JPanel with a JLabel as shown:
public static void main(String[] args) {
// init Frame
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
// !! add Buttons before you add the JLabel to the Frame !!!!
JButton clear = new JButton("Clear");
window.add(clear);
clear.setBounds(100, 100, 100, 100);
// !! change to JLabel!!
JLabel painting = new JLabel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// adds Antialising for rounded edges when adding text
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// test draw
g.setColor(Color.green);
g.fillRect(0, 0, 500, 500);
g.setColor(Color.black);
g.setFont(new Font("Consolas", 0, 100));
g.drawString("Test123'*#", 100, 300);
repaint();
}
};
window.add(painting);
window.setVisible(true);
}
Working Window without flickering
SIDENOTE: You need to add the buttons and other Components before you add the JLabel to the JFrame!
Also added Antialising as a small trick you can use for better visuals.
I Hope it'll help you!

Animating a painted object [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I've gone through and made classes for my objects and calls to them in my paint component, but I cant actually get them to move. Here is my move and check walls program that is in the object class:
public void move()
{
ballX += dx;
ballY += dy;
checkWalls();
}
//bounce of top/bottom, pass through left/right
public void checkWalls() {
//left-right
if(ballX > w) {
ballX = -diam;
}
else if(ballX < -diam) {
ballX = w;
}
//top-bottom
if(ballY < 0) {
dy *= -1;
}
else if(ballY + diam > h) {
dy *= -1;
}
}
And here is my call to them:
while(true) // infinite loop
{
jelly1.move();
frame.repaint();
try
{
Thread.sleep(10);
}
catch(Exception e){}
}
Also i feel the need to mention i have a background and a background component. The while(true) is in the background component because that's where the objects are created. And the frame is set visible in the background where the main method is.
Paint component is as follows:
public class BackgroundComponent extends JComponent {
Jellyfish jelly1;
Jellyfish jelly2;
Jellyfish jelly3;
Diver diver;
public BackgroundComponent() {
diver = new Diver(100, 300);
jelly1 = new Jellyfish(450, 450);
jelly2 = new Jellyfish(150, 300);
jelly3 = new Jellyfish(350, 75);
diver = new Diver(100, 300);
}
public void paintComponent(Graphics g){
//Drawing instructions go here
//Recover Graphics2D
Graphics2D g2 = (Graphics2D)g;
//Make gradient
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
int w = getWidth();
int h = getHeight();
Color color1 = Color.CYAN;
Color color2 = Color.BLACK;
GradientPaint gp = new GradientPaint(0, 0, color1, 0, h, color2);
g2.setPaint(gp);
g2.fillRect(0, 0, w, h);
//Constructs rectangles on edge of screen and draws them
Rectangle box = new Rectangle(0,0,75,700);
g.setColor(Color.LIGHT_GRAY);
g2.fill(box);
Rectangle box2 = new Rectangle(625, 0, 75, 700);
g.setColor(Color.LIGHT_GRAY);
g2.fill(box2);
//Draws lines, with a stroke of 5, over rectangles
Line2D.Double segment = new Line2D.Double(10, 0, 10, 700);
g2.setStroke(new BasicStroke(5));
g.setColor(Color.GRAY);
g2.draw(segment);
Line2D.Double segment2 = new Line2D.Double(30, 0, 30, 700);
g.setColor(Color.GRAY);
g2.draw(segment2);
Line2D.Double segment3 = new Line2D.Double(50, 0, 50, 700);
g.setColor(Color.GRAY);
g2.draw(segment3);
Line2D.Double segment4 = new Line2D.Double(70, 0, 70, 700);
g.setColor(Color.GRAY);
g2.draw(segment4);
Line2D.Double segment5 = new Line2D.Double(690, 0, 690, 700);
g.setColor(Color.GRAY);
g2.draw(segment5);
Line2D.Double segment6 = new Line2D.Double(670, 0, 670, 700);
g.setColor(Color.GRAY);
g2.draw(segment6);
Line2D.Double segment7 = new Line2D.Double(650, 0, 650, 700);
g.setColor(Color.GRAY);
g2.draw(segment7);
Line2D.Double segment8 = new Line2D.Double(630, 0, 630, 700);
g.setColor(Color.GRAY);
g2.draw(segment8);
//Draws rectangle around title with thick boarder
Rectangle box3 = new Rectangle(40,40,620,75);
g.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(5));
g2.draw(box3);
//Drawing text
String title = "Through the Depths";
//Sets font, font size, and color
g.setFont(new Font("Purisa", Font.BOLD, 50));
g.setColor(Color.DARK_GRAY);
g2.drawString(title, (50), 100);
//Places same text slightly up and over
g.setFont(new Font("Purisa", Font.BOLD, 50));
g.setColor(Color.WHITE);
g2.drawString(title, 53, 97);
//Draws ellipses with a stroke of 2 (these are the bubbles)
Ellipse2D.Double ellipse = new Ellipse2D.Double(450, 200, 150, 150);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
Ellipse2D.Double ellipse2 = new Ellipse2D.Double(510, 375, 90, 90);
g2.draw(ellipse2);
Ellipse2D.Double ellipse3 = new Ellipse2D.Double(470, 485, 70, 70);
g2.draw(ellipse3);
Ellipse2D.Double ellipse4 = new Ellipse2D.Double(510, 580, 45, 45);
g2.draw(ellipse4);
// Draws curves for bubbles
QuadCurve2D q = new QuadCurve2D.Float();
q.setCurve(548, 210, 607, 240, 590, 295);
g2.setStroke(new BasicStroke(3));
g2.draw(q);
QuadCurve2D q2 = new QuadCurve2D.Float();
q2.setCurve(575, 387, 607, 415, 585, 445);
g2.draw(q2);
QuadCurve2D q3 = new QuadCurve2D.Float();
g2.setStroke(new BasicStroke(2));
q3.setCurve(515, 493, 545, 511, 528, 540);
g2.draw(q3);
QuadCurve2D q4 = new QuadCurve2D.Float();
g2.setStroke(new BasicStroke(1));
q4.setCurve(538, 585, 558, 595, 545, 617);
g2.draw(q4);
// Sets color to pink before drawing jellyfish
g.setColor(Color.PINK);
//draws jellyfish
jelly1.draw(g);
jelly2.draw(g);
jelly3.draw(g);
// Draws diver
diver.draw(g);
while(true) // infinite loop
{
jelly1.move();
repaint();
try
{
Thread.sleep(10);
}
catch(Exception e){}
}
}
}
while(true){ ... } and Thread.Sleep inside a paintComponent implementation is completely the wrong way of doing things. By doing this, you are blocking the Event Dispatching Thread completely which means that your UI will no longer be updated properly and the UI will no longer be responsive.
What you should do:
Remove the while(true){ ... } loop from the paintComponent override
Create a javax.swing.Timer, set it to run every 10 milliseconds
In the ActionListener.actionPerformed implementation - the action that will be performed each 10 ms - move the jelly and call for a repaint
Start this timer after initialization is done, eg at the end of your constructor or initialization method (not paintComponent).
Stop the timer when it is no longer needed
Simplified example for this Timer, based on your snippet:
new javax.swing.Timer( 10, new ActionListener( ) {
#override
public void actionPerformed( ActionEvent e ) {
jelly1.move();
repaint();
}
}).start();

JFreeCharts Subtitles show up below legend?

I am using JFreeCharts and I have both the legend and subtitles positioned at the top of the chart. However, my desire is to have the title, then the subtitle in the second line, and then the legend underneath. Instead, it has the title, then legend, and then subtitle. This is the current layout:
As you can see, the legend is above the subtitles, whereas it should be the other way around. All of this, the title, legend, and subtitles, should be above the chart.
My current code to make the chart and customize the titles, subtitles, and legend are:
public JFreeChart createStackedChart(final CategoryDataset categorydataset, String Title) throws DocumentException, IOException {
final JFreeChart chart = ChartFactory.createStackedBarChart(
Title, // chart title
"", // domain axis label
"", // range axis label
categorydataset, // data
PlotOrientation.VERTICAL, // the plot orientation
true, // legend
true, // tooltips
false // urls
);
chart.setTitle(
new org.jfree.chart.title.TextTitle(Title,
new java.awt.Font("Calibri", java.awt.Font.PLAIN, 12)
));
chart.getTitle().setPaint(Color.GRAY);
Color subExc = new Color(237,125,49);
chart.addSubtitle(new TextTitle("Title",
new Font("Calibri", Font.PLAIN, 12), subExc,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
chart.addSubtitle(new TextTitle("Title2",
new Font("Calibri", Font.PLAIN, 12), Color.GRAY,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
LegendTitle legend = chart.getLegend();
legend.setPosition(RectangleEdge.TOP);
chart.getLegend().setFrame(BlockBorder.NONE);
legend.setItemPaint(Color.GRAY);
Font labelFont = new Font("Calibri", Font.PLAIN, 8);
legend.setItemFont(labelFont);
int columnCount = categorydataset.getColumnCount();
chart.setBackgroundPaint(Color.white);
chart.getTitle().setPadding(10, 2, 0, 2);
chart.setBorderVisible(true);
chart.setBorderPaint(Color.lightGray);
final CategoryPlot plot = chart.getCategoryPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.lightGray);
plot.setRangeGridlinePaint(Color.lightGray);
plot.setDomainGridlineStroke(new BasicStroke(0.5f));
plot.setRangeGridlineStroke(new BasicStroke(0.5f));
plot.setOutlineVisible(true);
plot.setOutlinePaint(Color.lightGray);
plot.setAxisOffset(new RectangleInsets(0, 0, 0, 0));
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setTickLabelFont(new Font("Calibri", Font.PLAIN, 9));
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setAutoRangeStickyZero(false);
rangeAxis.setLowerMargin(0.0);
rangeAxis.setTickLabelPaint(Color.GRAY);
rangeAxis.setTickMarkPaint(Color.lightGray);
rangeAxis.setTickMarkStroke(new BasicStroke(0.3f));
rangeAxis.setAxisLineStroke(new BasicStroke(0.3f));
rangeAxis.setLowerBound(0.0f);
rangeAxis.setAxisLinePaint(Color.lightGray);
GroupedStackedBarRenderer renderer = new GroupedStackedBarRenderer();
renderer.setDrawBarOutline(false);
renderer.setBarPainter(new StandardBarPainter());
Paint p1 = new GradientPaint(
0.0f, 0.0f, new Color(0x22, 0x22, 0xFF), 0.0f, 0.0f, new Color(0x88, 0x88, 0xFF)
);
renderer.setSeriesPaint(0, p1);
renderer.setSeriesPaint(4, p1);
renderer.setSeriesPaint(8, p1);
Paint p2 = new GradientPaint(
0.0f, 0.0f, new Color(0x22, 0xFF, 0x22), 0.0f, 0.0f, new Color(0x88, 0xFF, 0x88)
);
renderer.setSeriesPaint(1, p2);
renderer.setSeriesPaint(5, p2);
renderer.setSeriesPaint(9, p2);
Paint p3 = new GradientPaint(
0.0f, 0.0f, new Color(0xFF, 0x22, 0x22), 0.0f, 0.0f, new Color(0xFF, 0x88, 0x88)
);
renderer.setSeriesPaint(2, p3);
renderer.setSeriesPaint(6, p3);
renderer.setSeriesPaint(10, p3);
Paint p4 = new GradientPaint(
0.0f, 0.0f, new Color(0xFF, 0xFF, 0x22), 0.0f, 0.0f, new Color(0xFF, 0xFF, 0x88)
);
renderer.setSeriesPaint(3, p4);
renderer.setSeriesPaint(7, p4);
renderer.setSeriesPaint(11, p4);
renderer.setGradientPaintTransformer(
new StandardGradientPaintTransformer(GradientPaintTransformType.HORIZONTAL)
);
final CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setTickLabelPaint(Color.GRAY);
domainAxis.setTickLabelFont(new Font("Calibri", Font.PLAIN, 9));
Color transparent = new Color(0, 0, 0, 0);
domainAxis.setAxisLinePaint(transparent);
domainAxis.setTickMarkPaint(Color.lightGray);
domainAxis.setTickMarkStroke(new BasicStroke(0.3f));
domainAxis.setMaximumCategoryLabelWidthRatio(4f);
if (columnCount == 2) {
domainAxis.setCategoryMargin(.6);
domainAxis.setLowerMargin(0.015);
domainAxis.setUpperMargin(0.015);
} else if (columnCount == 3) {
domainAxis.setCategoryMargin(.35);
domainAxis.setLowerMargin(0.15);
domainAxis.setUpperMargin(0.15);
} else {
domainAxis.setCategoryMargin(.55);
domainAxis.setLowerMargin(0.015);
domainAxis.setUpperMargin(0.015);
}
if (columnCount >= 5) {
domainAxis.setCategoryLabelPositions(
CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 4.0));
chart.setPadding(new RectangleInsets(0, 5, 0, 5));
} else {
domainAxis.setCategoryLabelPositions(
STANDARD);
}
plot.setDomainAxis(domainAxis);
return chart;
}
What should I do besides RectangleEdge TOP to be able to determine the stacking order of the legend and subtitles? Thanks!
Actually, I have found a solution. Just in case this helps others out there. The source of inspiration for the answer was found in:
http://www.jfree.org/phpBB2/viewtopic.php?f=3&t=23187
I had to change my code to incorporate this. I wrote
chart.addSubtitle(0,new TextTitle("Title",
new Font("Calibri", Font.PLAIN, 12), subExc,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
chart.addSubtitle(1,new TextTitle("Title2",
new Font("Calibri", Font.PLAIN, 12), Color.GRAY,
RectangleEdge.TOP, HorizontalAlignment.CENTER,
VerticalAlignment.TOP, RectangleInsets.ZERO_INSETS));
Adding the 0 and 1 made these subtitles get written BEFORE the legend.
Here is a work-around that might do the trick for you:
Do not plot the legend in your chart: chart.removeLegend();
Wrap your ChartPanel inside a JPanel (with BorderLayout)
At the southern position of the panel, add your manually-generated legend:
Should look like:
public static JPanel wrapChart(ChartPanel chartPanel) {
JPanel panel = new JPanel(new BorderLayout());
panel.add(chartPanel, BorderLayout.CENTER);
panel.add(createLegend(chartPanel.getChart().getPlot()), BorderLayout.SOUTH);
return panel;
}
private static JPanel createLegend(Plot plot) {
JPanel panel = new JPanel(); // Using FlowLayout here
Iterator iterator = plot.getLegendItems().iterator();
while (iterator.hasNext()) {
LegendItem item = (LegendItem) iterator.next();
JLabel label = new JLabel(item.getLabel());
label.setIcon(new ColorIcon(8, item.getFillPaint()));
panel.add(label);
}
return panel;
}
(createLegend() method borrowed from this answer)

Java fullscreen mode breaks JPopupMenu. Still works, but doesn't render

I have a JPopupMenu that appears when a user right clicks on the window (as per usual with popups). When you're out in the middle of the screen, there's never a problem, but when you're up against the right side of the screen or the bottom, the menu just doesn't show up when in fullscreen mode.
Oddly enough, if you do the subsequent left click - pretending that the menu is there (because it actually is) - it will still select the correct value as if the menu's vertical and / or horizontal positions had been adjusted to compensate for the edges of the screen.
Even more oddly, this only happens on certain machines for reasons I can't fathom. E.g., I have two PCs here at work, both running Win7; one of them exhibits the failure, the other does not. On the machine that does exhibit the failure, the Win7 VM I have in it also does, but the Ubuntu VM does not. Now, one thing I noticed was that on the machines that do exhibit the rendering problem, the title bar of the JFrame disappears once full screen mode is entered, whereas the others do not (i.e. they still show the close and minimize buttons, making it seem like fullscreen exclusive mode on those machines was little more than maximizing).
Here is a fully functioning example of the problem (assuming your machine is magically susceptible to it) (enter fullscreen to see the problem)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.xml.ws.Holder;
public class ExclusiveModePopup {
public static void main(String[] args) {
final JFrame frame = new JFrame("Exclusive Popup test");
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Holder<Boolean> isInFullScreen = new Holder<Boolean>(false);
final Holder<String> lastSelected = new Holder<String>("");
final JPanel pane = new JPanel(new BorderLayout());
pane.add(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.DARK_GRAY);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
FontMetrics fm = g.getFontMetrics();
int fontHeight = fm.getMaxAscent();
g.setColor(Color.green);
g.drawOval(5, 5, 20, 20);
g.drawString("Right click here to see normal", 5, 25 + fontHeight);
if(!isInFullScreen.value){
g.drawOval(5, this.getHeight() - 30, 20, 20);
g.drawString("Right click here to see vertical adjustment",
5, this.getHeight() - 35);
g.drawOval(this.getWidth() - 30, 5, 20, 20);
String alongRight = "Right click here to see horizontal adjustment";
int strWidth = fm.charsWidth(alongRight.toCharArray(), 0, alongRight.length());
g.drawString(alongRight, this.getWidth() - 5 - strWidth, 25 + fontHeight);
g.drawOval(this.getWidth() - 30, this.getHeight() - 30, 20, 20);
alongRight = "Right click here to see both values adjusted";
strWidth = fm.charsWidth(alongRight.toCharArray(), 0, alongRight.length());
g.drawString(alongRight, this.getWidth() - 5 - strWidth, this.getHeight() - 35);
} else {
g.setColor(Color.red);
g.drawOval(5, this.getHeight() - 30, 20, 20);
g.drawString("Right click here to see failure",
5, this.getHeight() - 35);
g.drawOval(this.getWidth() - 30, 5, 20, 20);
String alongRight = "Right click here to see more failure";
int strWidth = fm.charsWidth(alongRight.toCharArray(), 0, alongRight.length());
g.drawString(alongRight, this.getWidth() - 5 - strWidth, 25 + fontHeight);
g.drawOval(this.getWidth() - 30, this.getHeight() - 30, 20, 20);
alongRight = "Right click here to see yet some moar failure";
strWidth = fm.charsWidth(alongRight.toCharArray(), 0, alongRight.length());
g.drawString(alongRight, this.getWidth() - 5 - strWidth, this.getHeight() - 35);
}
g.setColor(Color.white);
String lastSel = "Last selected value: " + lastSelected.value;
int strWidth = fm.charsWidth(lastSel.toCharArray(), 0, lastSel.length());
g.drawString(lastSel, this.getWidth() / 2 - strWidth / 2, this.getHeight() / 2);
}
}, BorderLayout.CENTER);
final JPopupMenu popup = new JPopupMenu();
for (int i = 0; i < 10; i++) {
final int j = i;
popup.add(new JMenuItem(new AbstractAction("Long name item number " + i){
#Override
public void actionPerformed(ActionEvent arg0) {
lastSelected.value = "Item #" + j;
pane.repaint();
}
}));
}
pane.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) == MouseEvent.BUTTON3_MASK) {
popup.show((Component) e.getSource(), e.getX(), e.getY());
}
}
});
final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
pane.add(new JButton(new AbstractAction("Toggle Fullscreen") {
#Override
public void actionPerformed(ActionEvent arg0) {
if (gd.isFullScreenSupported()) {
if (!isInFullScreen.value) {
gd.setFullScreenWindow(frame);
isInFullScreen.value = true;
} else {
gd.setFullScreenWindow(null);
isInFullScreen.value = false;
}
}
}
}), BorderLayout.SOUTH);
frame.setContentPane(pane);
Rectangle screenBounds = gd.getDefaultConfiguration().getBounds();
frame.setSize(800, 600);
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration());
frame.setLocation(screenBounds.width - frame.getWidth() - screenInsets.right,
screenBounds.height - frame.getHeight() - screenInsets.bottom);
frame.setVisible(true);
}
}
Thoughts? Thanks in advance.

Flashing JTextField and JButton

//ADDING BET FIELDS
setLayout(null);
horseChoice = new JTextField();
horseChoice.setBounds(200, 585, 300, 20);
add(horseChoice);
setLayout(null);
horseBet = new JTextField();
horseBet.setBounds(200, 625, 300, 20);
add(horseBet);
//ADDING BET BUTTON
setLayout(null);
bet = new JButton("Place Bet");
bet.setBounds(250, 675, 200, 50);
add(bet);
I am trying to create two textfields where the users can type in what they want and a button to save their input to a variable. But when I run my program, the text fields and button flash and then become invisible. Then if the user clicks on them they flash again. How do I stop this from happening?
The rest of the class:
// the "main" function
public void run(){
init();
font = new Font ("Arial", Font.BOLD, 14);
titleFont = new Font ("Comic Sans MS", Font.BOLD, 20);
textColor = new Color(100, 100, 100);
resultColor = new Color(255, 165, 0, 180);
//ADDING HORSES
horse1 = new Horses_1();
horse2 = new Horses_2();
horse3 = new Horses_3();
horse4 = new Horses_4();
//GAMELOOP
while (running){
start = System.nanoTime();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
try{
Thread.sleep(wait);
}
catch(Exception e){
e.printStackTrace();
}
//TIMER
if(horse1.h1x < 1350){
horse1Time++;
}
if(horse2.h2x < 1350){
horse2Time++;
}
if(horse3.h3x < 1350){
horse3Time++;
}
if(horse4.h4x < 1350){
horse4Time++;
}
//STOP RACING TIMERS
if(horse1Result == true && horse1.h1x >= 1350){
horse1TimeStr = horse1Time + ", Dominic";
horse1Result = false;
}
if(horse2Result == true && horse2.h2x >= 1350){
horse2TimeStr = horse2Time + ", Charlie";
horse2Result = false;
}
if(horse3Result == true && horse3.h3x >= 1350){
horse3TimeStr = horse3Time + ", Admiral";
horse3Result = false;
}
if(horse4Result == true && horse4.h4x >= 1350){
horse4TimeStr = horse4Time + ", Bacardi";
horse4Result = false;
}
//RANDOM HORSE CHOICE & MOVE PLACES
if(horse1.h1x >= 1350){
final int[] CHOICES = { 2,3,4 };
}
else if(horse2.h2x >= 1350){
final int[] CHOICES = { 1,3,4 };
}
else if(horse3.h3x >= 1350){
final int[] CHOICES = { 1,2,4 };
}
else if(horse4.h4x >= 1350){
final int[] CHOICES = { 1,2,3 };
}
else{
final int[] CHOICES = { 1,2,3,4 };
}
randomHorse = CHOICES[rand.nextInt(CHOICES.length)];
randomMove = rand.nextInt(35) + 1;
//PLACES
Update();
Draw();
drawToScreen();
}
}
// updates the game
private void Update() {
//UPDATE RACE COUNTER
if(horse1.h1x == 100 && horse2.h2x == 100 && horse3.h3x == 100 && horse4.h4x == 100){
races++;
}
//HORSE UPDATE
horse1.Update();
horse2.Update();
horse3.Update();
horse4.Update();
//RESULT SETTING
if(result == true && horse1Result == false && horse2Result == false && horse3Result == false && horse4Result == false){
String[] horses =
{ horse1TimeStr, horse2TimeStr, horse3TimeStr, horse4TimeStr };
Arrays.sort(horses);
firstHorse = horses[0];
secondHorse = horses[1];
thirdHorse = horses[2];
fourthHorse = horses[3];
firstHorse = firstHorse.replaceAll("[0-9,,]","");
secondHorse = secondHorse.replaceAll("[0-9,,]","");
thirdHorse = thirdHorse.replaceAll("[0-9,,]","");
fourthHorse = fourthHorse.replaceAll("[0-9,,]","");
result = false;
}
}
// draws the game onto an off-screen buffered image
private void Draw() {
//BACKGROUND COLOUR
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
if(button == true){
//ADDING BET FIELDS
setLayout(null);
horseChoice = new JTextField();
horseChoice.setBounds(200, 585, 300, 20);
add(horseChoice);
setLayout(null);
horseBet = new JTextField();
horseBet.setBounds(200, 625, 300, 20);
add(horseBet);
//ADDING BET BUTTON
setLayout(null);
bet = new JButton("Place Bet");
bet.setBounds(250, 675, 200, 50);
add(bet);
button = false;
}
horse1.Draw(g);
horse2.Draw(g);
horse3.Draw(g);
horse4.Draw(g);
//HORSE 1 - TRACK
g.setColor(new Color (255, 0, 0));
g.drawLine(100, 125, WIDTH - 100, 125);
//HORSE 2 - TRACK
g.setColor(new Color (0, 255, 0));
g.drawLine(100, 225, WIDTH - 100, 225);
//HORSE 3 - TRACK
g.setColor(new Color (0, 0, 255));
g.drawLine(100, 325, WIDTH - 100, 325);
//HORSE 4 - TRACK
g.setColor(new Color (255, 255, 0));
g.drawLine(100, 425, WIDTH - 100, 425);
//FINISH LINE
g.setColor(new Color (255, 255, 0));
g.drawLine(WIDTH - 100, 475, WIDTH - 100, 375);
g.setColor(new Color (0, 0, 255));
g.drawLine(WIDTH - 100, 275, WIDTH - 100, 375);
g.setColor(new Color (0, 255, 0));
g.drawLine(WIDTH - 100, 175, WIDTH - 100, 275);
g.setColor(new Color (255, 0, 0));
g.drawLine(WIDTH - 100, 75, WIDTH - 100, 175);
//HUD
g.setColor(new Color (180, 180, 180));
g.drawLine(50, 550, WIDTH - 50, 550);
g.drawLine(550, 550, 550, 700);
g.drawLine(900, 550, 900, 700);
g.setColor(resultColor);
g.setFont(titleFont);
g.drawString("Results", 700, 540);
g.drawString("Details", 1000, 540);
g.drawString("Betting", 360, 540);
//Results
g.setColor(textColor);
g.setFont(font);
g.drawString("Winner : ", 600, 600);
g.drawString("Second : ", 600, 630);
g.drawString("Third : ", 600, 660);
g.drawString("Fourth : ", 600, 690);
//DETAILS
g.drawString("Race Number :", 950, 600);
g.drawString("Horse Choice :", 950, 630);
g.drawString("Bet :", 950, 660);
g.setColor(resultColor);
g.drawString("" + races, 1250, 600);
//BETS
g.setColor(textColor);
g.drawString("Horse Choice :", 75, 600);
g.drawString("Bet :", 75, 640);
if(horse1Result == false && horse2Result == false && horse3Result == false && horse4Result == false){
g.setColor(resultColor);
g.drawString(" " + firstHorse, 780, 600);
g.drawString(" " + secondHorse, 780, 630);
g.drawString(" " + thirdHorse, 780, 660);
g.drawString(" " + fourthHorse, 780, 690);
}
g.setColor(textColor);
g.setFont(font);
//HORSE 1 TEXT
String h1 = "Dominic -";
g.drawString(h1, 10, 130);
//HORSE 2 TEXT
String h2 = "Charlie -";
g.drawString(h2, 10, 230);
//HORSE 3 TEXT
String h3 = "Admiral -";
g.drawString(h3, 10, 330);
//HORSE 4 TEXT
String h4 = "Bacardi -";
g.drawString(h4, 10, 430);
}
Looks like while(running) and Thread.sleep is giving your problems. For Swing apps use a javax.swing.Timer. Here is the basic construct
Timer(int delay, ActionListener listener)
where delay is the time to be delayed ("slept") between intervals and the listener is used just like a listener for a button, except you don't need to press a button for the event to fire, the Timer fires the event every delayed milliseconds. You can do something like this
Timer timer = new Timer(delay, new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// the stuff in your while loop here
}
});
timer.starts();
Here's an example of a Timer being used. Take a look at the docs for more methods you can use with the timer.
Side Note
It's not recommended to use a null layout. Take a look at Laying out Components within a Container for details on how to use Layout Managers, as you should be using instead of a null layout.

Categories