给定在JavaFX中实现的渲染器,将渲染器渲染到Canvas上。它运作良好。 这个渲染器需要在Swing应用程序中使用,并且由于JFXPanel组件在大多数用例中都可以正常工作,但JTable除外。如果用户想要使用给定渲染器渲染表单元格值,则应用程序会以多种不同方式开始失败。
这是一个示例应用程序:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.io.IOException;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.paint.Color;
public class TableRenderer {
private JFrame frame;
private JFrame createFrame(String title, JComponent component, int width, int height) {
final Dimension dimension = new Dimension(width, height);
JFrame frame = new JFrame(Util.getActiveScreenDevice().getDefaultConfiguration());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(dimension);
frame.setSize(dimension);
frame.add(component);
frame.setTitle(title);
Util.center(frame);
frame.pack();
return frame;
}
private void show() {
try {
init();
} catch (IOException e) {
e.printStackTrace();
}
frame.setVisible(true);
}
private void init() throws IOException {
JTable table = new JTable(new TableModel());
table.setRowHeight(200);
table.setDefaultRenderer(Object.class, new CellRenderer());
JScrollPane p = new JScrollPane(table);
table.setFillsViewportHeight(true);
frame = createFrame("Renderer Demo - JTable", p, 420, 220);
}
public static void main(String[] args) {
TableRenderer app = new TableRenderer();
SwingUtilities.invokeLater(app::show);
}
@SuppressWarnings("serial")
private static class TableModel extends AbstractTableModel {
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return "this is cell at ("+columnIndex+"; "+rowIndex+")";
}
@Override
public int getRowCount() {
return 3;
}
@Override
public int getColumnCount() {
return 3;
}
};
private static class CellRenderer implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
Rectangle cellRect = table.getCellRect(row, column, true);
Renderer renderer = new Renderer(cellRect.getSize(), value);
renderer.setSize(cellRect.getSize());
renderer.setPreferredSize(cellRect.getSize());
renderer.setBackground(java.awt.Color.BLACK);
return renderer;
}
}
@SuppressWarnings("serial")
private static class Renderer extends JFXPanel {
public Renderer(Dimension cellRect, Object value) {
super();
Group root = new Group();
Scene scene = new Scene(root);
Canvas canvas = new Canvas(cellRect.getWidth(), cellRect.getHeight());
canvas.getGraphicsContext2D().setFill(Color.RED);
canvas.getGraphicsContext2D().fillText(value.toString(), 10, 10);
canvas.getGraphicsContext2D().fillOval(10, 10, 10, 10);
root.getChildren().add(canvas);
setScene(scene);
}
}
}
在这种情况下,单元格中没有任何内容,应用程序冻结。
如果在JPanel
中显示,同样的工作就可以了import java.awt.Dimension;
import java.io.IOException;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.paint.Color;
public class PanelRenderer {
private JFrame frame;
private JFrame createFrame(String title, JComponent component, int width, int height) {
final Dimension dimension = new Dimension(width, height);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(dimension);
frame.setSize(dimension);
frame.add(component);
frame.setTitle(title);
Util.center(frame);
frame.pack();
return frame;
}
private void show() {
try {
init();
} catch (IOException e) {
e.printStackTrace();
}
frame.setVisible(true);
}
private void init() throws IOException {
JPanel p = new JPanel();
p.add(new Renderer(new Dimension(200, 200), "Demo"));
frame = createFrame("Renderer Demo - JPanel", p, 200, 200);
}
public static void main(String[] args) {
PanelRenderer app = new PanelRenderer();
SwingUtilities.invokeLater(app::show);
}
@SuppressWarnings("serial")
private static class Renderer extends JFXPanel {
public Renderer(Dimension cellRect, Object value) {
super();
Group root = new Group();
Scene scene = new Scene(root);
Canvas canvas = new Canvas(cellRect.getWidth(), cellRect.getHeight());
canvas.getGraphicsContext2D().setFill(Color.RED);
canvas.getGraphicsContext2D().fillText(value.toString(), 10, 10);
canvas.getGraphicsContext2D().fillOval(10, 10, 10, 10);
root.getChildren().add(canvas);
setScene(scene);
}
}
}
我尝试在JPanel中添加渲染器,并将其作为单元格渲染器组件返回,不做任何更改。
我试图同步FXThread和EDT,这是一个地狱,没有任何反应。
我尝试渲染图像,创建一个Component,覆盖paintComponent以绘制图像,并同步线程。这似乎适用于Windows,但在OSX上仍然失败。
我做错了什么,或者我应该接受这个用例是来自魔鬼而无法让它起作用?