我在制作JLabel和textFields时遇到了一些麻烦。 如果我将所有这些代码放在main方法中它可以正常工作,但是当我将JLabel和TextFields移动到它们自己的方法或类中时,JPanel仍然是空的。我用的图像显示了。
package gui;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
@SuppressWarnings("serial")
class ImagePanel extends JPanel {
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
setSize(size);
setLayout(null);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, null);
}
}
public class EquippedInput {
private JPanel panel;
public static void main(String[] args){
ImagePanel panel = new ImagePanel(new ImageIcon("Images/Crusader Background.jpg").getImage());
JScrollPane scrollBar = new JScrollPane(panel,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
panel.setLayout(null);
JFrame frame = new JFrame();
frame.getContentPane().add(scrollBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1160, 1000);
frame.setVisible(true);
panel.setPreferredSize(new Dimension(1125, 1210));
scrollBar.getVerticalScrollBar().setUnitIncrement(20);
}
public EquippedInput() {
initialize();
}
private void initialize() {
/**
* Stats and slots labels.
*/
JLabel lblWeaponAttacksPerSecond = new JLabel("Weapon Attacks Per Second");
JLabel lblWeaponAttackSpeed = new JLabel("Attack Speed");
JLabel lblMainHand = new JLabel("Main Hand");
JLabel lblOffHand = new JLabel("Off Hand");
JLabel stats[] = {lblWeaponAttacksPerSecond, lblWeaponAttackSpeed};
JLabel slots[] = {lblMainHand, lblOffHand};
/**
* Place stats and slots labels.
*/
for (int i = 0; i < stats.length; i++) {
stats[i].setBounds(10, (40 + 30 * i), 200, 20);
panel.add(stats[i]);
}
for (int i = 0; i < slots.length; i++) {
slots[i].setBounds((220 + 70 * i), 10, 60, 20);
panel.add(slots[i]);
}
/**
* Text fields.
*/
JTextField textField0 = new JTextField();
JTextField textField1 = new JTextField();
JTextField mainHandTextField[] = {textField0, textField1};
/**
* Arrays of whether a stat can roll on an item. 1 = can roll. 0 = can't roll.
*/
int mainHandAvailableStats[] = {0, 1};
/**
* Text field builders, each loop is a single slot.
*/
for (int i = 0; i < mainHandTextField.length; i++) {
panel.add(mainHandTextField[i]);
if(mainHandAvailableStats[i] == 1) {
int textFieldVerticalPosition = 40 + 30 * i;
mainHandTextField[i].setBounds(220, textFieldVerticalPosition, 60, 20);
panel.add(mainHandTextField[i]);
}
}
}
}
实际代码为JPanel提供了更多内容,但这会产生完全相同的结果。
答案 0 :(得分:2)
我将不得不稍后解释这段代码和这个答案,但它显示:
数据文件是:
Main_Hand Off_Hand Head Shoulder Neck
Weapon_Attacks_per_sec 5 null null null null
Attack_Speed 20 null null null null
Damage_% 30 null null null null
Min_Bonus_Damage 3 null null null null
Max_Bonus_Damage 40 null null null null
Min_Weapon_Damage 30 null null null null
Max_Weapon_Damage 80 null null null null
Strength 70 50 20 30 30
它必须命名为TableFunData.txt
,并且与代码所在的目录/包中相同。
代码是:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Scanner;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
@SuppressWarnings("serial")
public class TableFun extends JPanel {
private static final String IMG_PATH = "https://upload.wikimedia.org/"
+ "wikipedia/commons/d/d1/Ozanne-Brest.jpg";
private JTable table = new JTable();
private BufferedImage img;
public TableFun(BufferedImage img, TableModel model) {
this.img = img;
table = new JTable(model);
table.setDefaultRenderer(Object.class, new MyCellRenderer());
table.setOpaque(false);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.setShowGrid(false);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
if (isPreferredSizeSet() || img == null) {
return superSize;
}
int supW = superSize.width;
int supH = superSize.height;
int imgW = img.getWidth();
int imgH = img.getHeight();
int w = Math.max(imgW, supW);
int h = Math.max(imgH, supH);
return new Dimension(w, h);
}
private class MyCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (column != 0) {
renderer.setHorizontalAlignment(JLabel.CENTER);
} else {
renderer.setHorizontalAlignment(JLabel.LEADING);
}
renderer.setOpaque(value != null);
return renderer;
}
}
private static void createAndShowGui() {
BufferedImage img = null;
try {
URL imageUrl = new URL(IMG_PATH);
img = ImageIO.read(imageUrl);
} catch (IOException e1) {
e1.printStackTrace();
System.exit(-1);
}
String dataPath = "TableFunData.txt";
DataIO dataIO = new DataIO(dataPath);
TableModel model = null;
try {
model = dataIO.createTableModel();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
JFrame frame = new JFrame("Table Fun");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TableFun(img, model));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class DataIO {
private static final String NULL = "null";
private String dataPath;
public DataIO(String dataPath) {
this.dataPath = dataPath;
}
public TableModel createTableModel() throws IOException {
InputStream inputStream = getClass().getResourceAsStream(dataPath);
Scanner scanner = new Scanner(inputStream);
Vector<String> columnNames = new Vector<>();
Vector<Vector<Object>> data = new Vector<>();
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (columnNames.size() == 0) {
columnNames = createColumnNames(line);
} else {
Vector<Object> dataRow = createDataRow(line);
data.add(dataRow);
}
}
if (scanner != null) {
scanner.close();
}
DefaultTableModel model = new DefaultTableModel(data, columnNames);
return model;
}
private Vector<String> createColumnNames(String line) {
String[] tokens = line.split("\\s+");
Vector<String> columnNames = new Vector<>();
columnNames.add(" "); // first name is blank
for (String token : tokens) {
if (!token.trim().isEmpty()) {
token = token.replace("_", " "); // add spaces
columnNames.add(token);
}
}
return columnNames;
}
private Vector<Object> createDataRow(String line) {
String[] tokens = line.split("\\s+");
Vector<Object> dataRow = new Vector<>();
for (String token : tokens) {
token = token.trim();
if (!token.isEmpty()) {
// first token is the title
if (dataRow.size() == 0) {
token = token.replace("_", " "); // add spaces
dataRow.add(token);
} else {
// if title already added
if (token.equalsIgnoreCase(NULL)) {
dataRow.add(null);
} else {
int value = Integer.parseInt(token);
dataRow.add(value);
}
}
}
}
return dataRow;
}
}
GUI看起来像:
现在有一些解释:
好的,这段代码的作用是什么:
首先,我使用外部图像,可以从维基百科/维基媒体免费获得,以便我的代码可以从任何计算机运行,并演示在JPanel中使用图像。图像路径可以在这里找到:
private static final String IMG_PATH = "https://upload.wikimedia.org/"
+ "wikipedia/commons/d/d1/Ozanne-Brest.jpg";
并且它在这里用于创建图像:
URL imageUrl = new URL(IMG_PATH);
img = ImageIO.read(imageUrl);
然后在JPanel的paintComponent方法中绘制:
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
我的代码还扩展了JPanel,因为这为我的GUI程序提供了比他们扩展JFrame时更大的灵活性:
public class TableFun extends JPanel {
我覆盖了JPanel的getPreferredSize方法,使其大小适合图片,除非需要更大。这就是为什么我首先获得超级首选尺寸,并尝试使我的GUI足够大以显示图像,如果需要显示更多组件则更大:
@Override
public Dimension getPreferredSize() {
Dimension superSize = super.getPreferredSize();
if (isPreferredSizeSet() || img == null) {
return superSize;
}
int supW = superSize.width;
int supH = superSize.height;
int imgW = img.getWidth();
int imgH = img.getHeight();
int w = Math.max(imgW, supW);
int h = Math.max(imgH, supH);
return new Dimension(w, h);
}
为了简化代码,我尝试将代码与数据分开,并将我的数据放在文本文件中。 DataIO类是一个小实用程序类,用于读取文件所持有的文本,然后逐行解析数据以创建和填充DefaultTableModel对象。请注意,我得到的文件不是&#34;文件&#34;而是作为一个类资源,因为这样我可以将它包含在jar文件中,如果我想这样做的话。我使用扫描仪读取每一行,就像你为文本文件所做的那样。
public TableModel createTableModel() throws IOException {
InputStream inputStream = getClass().getResourceAsStream(dataPath);
Scanner scanner = new Scanner(inputStream);
一旦我得到一行文字,我就用白色空格分割它,这会创建一个字符串数组,并修剪掉所有空格:
String[] tokens = line.split("\\s+");
JTable使用名为MyCellRenderer的表格单元格渲染器
table.setDefaultRenderer(Object.class, new MyCellRenderer());
如果单元格保存数据,则使单元格不透明;如果单元格保持空值,则使其不透明(清除):
renderer.setOpaque(value != null);
我还确保JTable本身,JScrollPane和scrollpane的视口都是非透明的,这样图像就可以显示出来:
table.setOpaque(false);
// ....
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
你提到了一个被抛出的NPE,这可能意味着你的Java程序没有找到文本文件。同样,它必须与您的类文件一起放置。您应该在与java文件相同的目录中创建一个Eclipse 的文本文件,将其精确命名为 TableFunData.txt (拼写和大小写),以及何时#&重新完成,Eclipse应该看起来像:
使用Eclipse的软件包资源管理器(以蓝色和红色突出显示)在同一个软件包中看到代码和数据文本,代码的软件包语句应该显示它实际上在这里包装(绿色)。
答案 1 :(得分:0)
这是一个简单的JTable实现,正如@Hovercraft Full Of Eels所建议的那样。 基于数据呈现背景颜色。 1将导致背景颜色为蓝色,而0将呈现为红色。 (该演示基于https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/components/SimpleTableDemoProject/src/components/SimpleTableDemo.java)
public class TableDemo extends JPanel {
public TableDemo() {
super(new GridLayout(1,0));
String[] columnNames = {" ",
"Main Hand",
"Off Hand",
"Head",
"Shoulder",
"Neck"};
Object[][] data = {
{"Weapon Attacks Per Second", new Integer(1), new Integer(0), new Integer(0),new Integer(0),new Integer(0)},
{"Attack Speed", new Integer(1), new Integer(0), new Integer(1),new Integer(0),new Integer(0)},
{"Damage%", new Integer(1), new Integer(0), new Integer(0),new Integer(0),new Integer(0)},
{"Min Bonus Damage", new Integer(1), new Integer(0), new Integer(0),new Integer(1),new Integer(0)},
{"Max Bonus Damage", new Integer(1), new Integer(1), new Integer(0),new Integer(0),new Integer(0)},
{"Min Weapon Damage", new Integer(1), new Integer(0), new Integer(0),new Integer(1),new Integer(0)},
{"Max Weapon Damage", new Integer(1), new Integer(0), new Integer(1),new Integer(0),new Integer(0)},
};
final JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(new Dimension(600, 70));
table.getColumnModel().getColumn(1).setCellRenderer(new ColorRenderer());
table.getColumnModel().getColumn(2).setCellRenderer(new ColorRenderer());
table.getColumnModel().getColumn(3).setCellRenderer(new ColorRenderer());
table.getColumnModel().getColumn(4).setCellRenderer(new ColorRenderer());
table.getColumnModel().getColumn(5).setCellRenderer(new ColorRenderer());
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TableDemo newContentPane = new TableDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
}
class ColorRenderer extends DefaultTableCellRenderer {
public ColorRenderer() {
setOpaque(true); //MUST do this for background to show up.
}
@Override
public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected,
boolean hasFocus,int row, int column) {
if((int)value == 1) {
setBackground(Color.BLUE);
}else {
setBackground(Color.RED);
}
return this;
}
}