I have a project that uses JFreeChart
.
The chart that I am using is displaying correctly and works fine with the current code.
My problem is that I can only position the graph to the east, south, west, center or north of my JPanel
.
My desire is to move this chart to any position inside my JPanel
.
This is the short code snippet where I add my graph to the panSimulator
JPanel
. The problematic code is at the bottom of the ConfigurationFrame
class:
public class ConfigurationFrame extends JFrame {
private KettlerBikeConnector bike1 = null;
private static final long serialVersionUID = 1L;
CrosshairDemo chd = new CrosshairDemo();
private JPanel panSimulator;
private PanelBikeSimulator panBSim;
private Timer timerBike;
private TimerListener listener;
private final int UPDATE_MS = 1000; // updates every second
private JTabbedPane tabPane;
private JPanel panConfiguration;
private JPanel panGame;
private JComboBox<String> cbxPort;
private JTextPane lblStatus;
// to have access to the textfield
public static JTextField txtEnergy;
public static JTextField txtDistance;
public static JTextField txtHeartRate;
public static JTextField txtTime;
public File path = null;
public int key = -1;
boolean run = true;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ConfigurationFrame frame = new ConfigurationFrame();
frame.setVisible(true);
// frame.pack(); // give a suitable size to window automatically
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
*/
public ConfigurationFrame() throws ParserConfigurationException, SAXException, IOException {
setResizable(false);
setMinimumSize(new Dimension(1900, 1000));
setTitle("Bike Simulation ... I need a name ...");
setLocationRelativeTo(null);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent arg0) {
try {
timerBike.stop();
bike1.close();
} catch (Exception e) {
log(e.getMessage());
}
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
getContentPane().setLayout(null);
// Panel
tabPane = new JTabbedPane(JTabbedPane.TOP);
tabPane.setFont(new Font("Tahoma", Font.PLAIN, 24));
tabPane.setBounds(0, 0, 1892, 994);
getContentPane().add(tabPane);
// Configuration-Panel
panConfiguration = new JPanel();
tabPane.addTab("Configuration", null, panConfiguration, null);
panConfiguration.setLayout(null);
// ComboBox for Kettler
cbxPort = new JComboBox<String>();
cbxPort.setFont(new Font("Tahoma", Font.PLAIN, 24));
cbxPort.setBounds(734, 5, 247, 49);
panConfiguration.add(cbxPort);
// Button-Connection
JButton btnConnect = new JButton("Connect");
btnConnect.setFont(new Font("Tahoma", Font.PLAIN, 24));
btnConnect.setBounds(157, 7, 137, 49);
btnConnect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
bike1 = new KettlerBikeConnector();
bike1.connect(cbxPort.getSelectedItem().toString(), new KettlerBikeListener() {
@Override
public void bikeAck() {
switch (listener.state) {
case hello:
listener.state = State.connected;
break;
case reset:
listener.state = State.hello;
break;
case connected:
log("connection successful");
break;
case notConnected:
log("not connected");
break;
}
}
@Override
public void bikeData(DataRecord data) {
//Sending the Ergometer velcoity every 1000ms to the
panBSim.setErgometerVelocity(data.getSpeed() / 10);
panBSim.setErgometerRPM(data.getPedalRpm());
panBSim.setTrueDataHere(true);
double power = panBSim.getTraveledDistance();
chd.setPower(power);
//getPower und dann set hier die Ergometer widerstand
try {
bike1.sendSetPower(panBSim.getErgometerPower());
} catch (IOException ignored) {
System.out.println("ignored");
}
}
@Override
public void bikeDestPowerChanged(int power) {
log("dest power: " + power);
}
@Override
public void bikeError() {
log("error1");
}
});
} catch (Exception e) {
log(e.getMessage());
}
}
});
panConfiguration.add(btnConnect);
// Button-Start
JButton btnStart = new JButton("Start");
btnStart.setFont(new Font("Tahoma", Font.PLAIN, 24));
btnStart.setBounds(304, 7, 137, 49);
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
listener = new TimerListener(bike1);
timerBike = new Timer(UPDATE_MS, listener);
timerBike.start();
tabPane.setSelectedComponent(panSimulator); // switch to GamePanel
panBSim.startSimulate();
} catch (Exception e) {
log(e.getMessage());
}
}
});
panConfiguration.add(btnStart);
// Button-Scan
JButton btnScan = new JButton("Scan");
btnScan.setFont(new Font("Tahoma", Font.PLAIN, 24));
btnScan.setBounds(10, 7, 137, 49);
btnScan.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers(); // list of named
while (portList.hasMoreElements()) {
CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
cbxPort.addItem(portId.getName());
if (portId.isCurrentlyOwned()) {
log("Port " + portId.getName() + " is already open");
}
}
}
}
});
panConfiguration.add(btnScan);
// Status displays information regarding connection
lblStatus = new JTextPane();
lblStatus.setText(
"Anweisung:\r\n\t1) W\u00E4hle ein Lebensmittel aus der Food-Item Combobox aus\r\n\t2) Dr\u00FCcke den Scan-Button und w\u00E4hle den Port aus der Port Combobox aus\r\n\t3) Dr\u00FCcke den Connect-Button, um die Ger\u00E4te zu verbinden\r\n\t4) Dr\u00FCcke den Start-Button, um die Anwendung zu starten\r\n\t5) Warte auf das akustische Signal des Ergometer\r\n\t6) Beginne zu treten");
lblStatus.setFont(new Font("Tahoma", Font.PLAIN, 24));
lblStatus.setBounds(10, 125, 971, 229);
lblStatus.setDisabledTextColor(Color.BLACK);
lblStatus.setSelectionColor(new Color(51, 153, 255));
panConfiguration.add(lblStatus);
// FH Logo
JLabel lblLogo = new JLabel("");
lblLogo.setBounds(10, 365, 971, 430);
try {
File in = new File("FHLogo.png");
Image logo = ImageIO.read(in);
Image scaledLogo = logo.getScaledInstance(lblLogo.getWidth(), lblLogo.getHeight(), Image.SCALE_SMOOTH);
ImageIcon iconLogo = new ImageIcon(scaledLogo);
lblLogo.setIcon(iconLogo);
} catch (IOException e2) {
e2.printStackTrace();
}
panConfiguration.add(lblLogo);
// Labels
JLabel lblPort = new JLabel("Port:");
lblPort.setFont(new Font("Tahoma", Font.PLAIN, 24));
lblPort.setBounds(600, 5, 124, 49);
panConfiguration.add(lblPort);
//-----------------------------------------------------------------------------XXX
//Tab Bike Simulator
BorderLayout bdl = new BorderLayout();
panSimulator = new JPanel();
tabPane.addTab("Bike Simulator", null, panSimulator, null);
panSimulator.setLayout(bdl);
//Panel Bike Simulator
//panBSim = new PanelBikeSimulator();
//panBSim.setBorder(BorderFactory.createLineBorder(Color.black));
panSimulator.add(chd.getContentPane(), bdl.NORTH);
}
/**
* To log information
*
* @param str String that is shown
*/
private void log(String str) {
lblStatus.setText(lblStatus.getText() + str + "\n");
}
}
And this class belongs to my chart that I want to move to any location in my JPanel.
public class CrosshairDemo extends JFrame {
private static double POWER = 0.0;
public void setPower(double power) {
POWER = power;
}
public CrosshairDemo() {
super();
this.setContentPane(new CrosshairDemo.MyDemoPanel());
}
public static class MyDemoPanel extends JPanel implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
Thread t = new Thread((Runnable) this);
private TimeSeries series;
private final ChartPanel chartPanel;
private final JFreeChart chart = this.createChart();
public MyDemoPanel() {
super(new BorderLayout());
this.chartPanel = new ChartPanel(this.chart);
this.chartPanel.setPreferredSize(new Dimension(200, 550));
this.chartPanel.setLocation(getWidth() + 50, getHeight() + 30);
this.chartPanel.setDomainZoomable(true);
this.chartPanel.setRangeZoomable(true);
this.add(this.chartPanel);
t.start();
}
private JFreeChart createChart() {
XYDataset dataset1 = this.createDataset("Random 1", 100.0D, new Minute(), 200);
JFreeChart chart1 = ChartFactory.createTimeSeriesChart("Crosshair Demo 1", "Time of Day", "Value", dataset1);
XYPlot plot = (XYPlot)chart1.getPlot();
plot.setOrientation(PlotOrientation.VERTICAL);
plot.setDomainCrosshairVisible(true);
plot.setDomainCrosshairLockedOnData(false);
plot.setRangeCrosshairVisible(false);
return chart1;
}
private XYDataset createDataset(String name, double base, RegularTimePeriod start, int count) {
this.series = new TimeSeries(name);
RegularTimePeriod period = start;
double value = base;
for(int i = 0; i < count; ++i) {
this.series.add(period, value);
period = period.next();
value *= 1.0D + (Math.random() - 0.495D) / 10.0D;
}
TimeSeriesCollection dataset = new TimeSeriesCollection();
dataset.addSeries(this.series);
return dataset;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
int value = (int) POWER; //this.slider.getValue();
XYPlot plot = (XYPlot)this.chart.getPlot();
ValueAxis domainAxis = plot.getDomainAxis();
Range range = domainAxis.getRange();
double c = domainAxis.getLowerBound() + (double)value / 100.0D * range.getLength();
plot.setDomainCrosshairValue(c);
}
}
}
Right now it's "attached" to the top (NORTH) of my JPanel:
Current chart position:
I would appreciate any help, because I have no more idea how to position this chart freely, therefore, I need your help guys.