#java
#java
Вопрос:
Я надеюсь, что это не слишком похоже на вопрос новичка. Я раньше не занимался программированием в графическом стиле. Моя цель — создать рекламную игру в пинбол в апплете. Тем не менее, я сталкиваюсь с одним из первых препятствий. Мой апплет не отображает результаты метода paintComponent из моего класса Table (который расширяет JPanel). Я попробовал несколько вещей, например, как я загружаю изображение (в настоящее время использую двойную буферизацию, но раньше я использовал mediatracker), проверяя, позволит ли отсутствие каких-либо других элементов графического интерфейса отображать изображение (поскольку я задавался вопросом, не рисуется ли оно каким-то образом под ним) и другие вещи. Эта проблема поставила меня в тупик, и я начинаю задаваться вопросом (и надеяться), не упустил ли я из виду что-то маленькое, если это так, то я сожалею, но все равно был бы благодарен за помощь, поскольку я не могу далеко продвинуться, не устранив сначала эту проблему. Мой код для моего Pinball (апплета) и класса Table приведены ниже, другие классы еще не реализованы. Еще раз, я ценю любую помощь.
import javax.swing.*; // useful for the drawing side, also going to be a JApplet
import java.awt.*;
import java.net.*;
public class Pinball extends JApplet {
// variables go here
Table table;
// further initialisation of the GUI
public void init() {
setSize(300, 300);
table = new Table(this);
add(table);
setContentPane(table); // makes our graphical JPanel container the content pane for the Applet
// createGUI(); // this has been moved onto the table class
}
public void stop() {
}
}
А теперь класс Table:
import java.awt.*; // needed for old style graphics stuff
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*; // gives us swing stuff
import java.io.IOException;
import java.net.*; // useful for anything using URLs
public class Table extends JPanel {
// attributes go here
Pinball pb;
Color bgColour;
JPanel eastPanel;
JPanel logoPanel;
JPanel livesPanel;
JPanel scorePanel;
JPanel tablePanel;
JPanel scrollTextPanel;
Image logo;
// constructor goes here
public Table(Pinball pb) {
setPreferredSize(new Dimension(300, 300));
this.pb = pb;
// this is not needed anymore, with the new loadImage class down the bottom
// Toolkit tk = Toolkit.getDefaultToolkit(); // needed to get images
// logo = tk.getImage(base "images/logo.jpg");
logo = loadImage("logo.jpg");
createGUI();
}
// public methods go here
// all GUI creation stuff goes here
public void createGUI() {
/* allows the three parts (top, middle and right)
* to be made through (north, center and right) */
setLayout(new BorderLayout());
// setting the background colour
bgColour = new Color(190, 186, 221); // makes the sky blue colour for the background.
setBackground(bgColour);
// now putting a panel for the east side
eastPanel = new JPanel();
eastPanel.setBackground(bgColour);
eastPanel.setLayout(new BorderLayout(8, 8));
eastPanel.setPreferredSize(new Dimension(100, 280));
logoPanel = new JPanel();
logoPanel.setBackground(Color.WHITE);
logoPanel.setPreferredSize(new Dimension(100, 100));
logoPanel.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.white));
//JLabel label1 = new JLabel("Logos go here");
//logoPanel.add(label1);
eastPanel.add(logoPanel, "North");
livesPanel = new JPanel();
livesPanel.setBackground(Color.WHITE);
livesPanel.setPreferredSize(new Dimension(100, 100));
JLabel label2 = new JLabel("Lives go here");
livesPanel.add(label2);
eastPanel.add(livesPanel, "Center");
scorePanel = new JPanel();
scorePanel.setBackground(Color.WHITE);
scorePanel.setPreferredSize(new Dimension(100, 80));
JLabel label3 = new JLabel("Scores go here");
scorePanel.add(label3);
eastPanel.add(scorePanel, "South");
add(eastPanel, "East");
tablePanel = new JPanel();
tablePanel.setBackground(bgColour);
tablePanel.setPreferredSize(new Dimension(200, 280));
add(tablePanel, "Center");
scrollTextPanel = new JPanel();
scrollTextPanel.setPreferredSize(new Dimension(300, 20));
scrollTextPanel.setBackground(Color.WHITE);
scrollTextPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(scrollTextPanel, "North");
// repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(logo, 5, 5, 90, 90, null);
g.drawLine(0, 0, 300, 300); // for testing, does not work
}
// a little useful method for handling loading of images and stuff
public BufferedImage loadImage(String filename) {
BufferedImage image = null;
try {
URL url = new URL(pb.getCodeBase(), "images/" filename);
image = ImageIO.read(url);
} catch (IOException e) {
}
return image;
}
}
Комментарии:
1. Добавление компонентов при инициализации в ваш подкласс JPanel плюс переопределение paintComponent не будут хорошо сочетаться друг с другом.
2. @justkt: они могут воспроизводиться красиво, если для свойства непрозрачности покрывающего компонента установлено значение false. Пожалуйста, смотрите мой ответ ниже.
Ответ №1:
Ваша таблица JPanel закрыта другими JPanels, что может быть нормально, но вы не сможете видеть сквозь непрозрачный компонент, который ее покрывает, в частности, tablePanel JPanel. Например, попробуйте:
tablePanel = new JPanel();
// tablePanel.setBackground(bgColour); //!! removed
tablePanel.setOpaque(false); //!! added
И посмотрим, что произойдет.
Не связанный с этим вопрос к вам относительно этого кода здесь:
public void init() {
setSize(300, 300);
table = new Table(this);
add(table);
setContentPane(table); // makes our graphical JPanel container the content
Почему вы добавляете объект table Table дважды, один раз в панель содержимого JApplet, а затем следующий как панель содержимого JApplet?
Комментарии:
1. Я был слишком медлителен в этом вопросе. 😉
2. Привет, и спасибо за быстрый ответ. К сожалению, это сработало не идеально, но это моя ошибка. Я переместил его, чтобы показать логотип на 5, 5, чтобы посмотреть, был ли это мой предыдущий набор координат (из logoPanel). Я использовал logoPanel.getX () 5 и logoPanel.getY () 5, чтобы получить координаты раньше, и не был уверен, что именно поэтому они не отображаются. Однако ваш код действительно сработал. Я начинаю задаваться вопросом, для такого графического проекта, как этот, было бы лучше использовать всю графику и никаких компонентов? Это мой первый опыт работы с графикой.
3. Привет, @Hovercraft, полный угрей, спасибо за ваш быстрый ответ. Ваш код действительно работал, но я не могу использовать его эффективно, хотя это моя ошибка. Я намеревался отобразить логотип на logoPanel, но я использовал код, в котором не был уверен, что это сработает, поэтому я попытался устранить эту проблему, переместив изображение. Код, который я использовал ранее для позиционирования, был (logo, logoPanel.getX() 5, logoPanel.getY() 5 …) и т.д. Это сработает? При необходимости я могу использовать абсолютные координаты.
4. Извините за тройной пост, я не понял, как удалять комментарии.
Ответ №2:
Запустите, затем изучите этот код и посмотрите, сможете ли вы определить источник проблемы.
// <applet code='Pinball' width='300' height='300'></applet>
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*; // useful for the drawing side, also going to be a JApplet
import javax.imageio.ImageIO;
import java.net.*;
import java.io.IOException;
public class Pinball extends JApplet {
// variables go here
Table table;
// further initialisation of the GUI
public void init() {
table = new Table(this);
setContentPane(table); // makes our graphical JPanel container the content pane for the Applet
}
}
class Table extends JPanel {
// attributes go here
Pinball pb;
Color bgColour;
JPanel eastPanel;
JPanel logoPanel;
JPanel livesPanel;
JPanel scorePanel;
JPanel tablePanel;
JPanel scrollTextPanel;
Image logo;
// constructor goes here
public Table(Pinball pb) {
//setPreferredSize(new Dimension(300, 300));
this.pb = pb;
// this is not needed anymore, with the new loadImage class down the bottom
//Toolkit tk = Toolkit.getDefaultToolkit(); // needed to get images
//logo = tk.getImage(base "images/logo.jpg");
int size = 100;
logo = //loadImage("logo.jpg");
new BufferedImage( size,size, BufferedImage.TYPE_INT_RGB);
Graphics g = logo.getGraphics();
g.setColor(Color.red);
g.fillRect(0,0,size,size);
createGUI();
}
// public methods go here
// all GUI creation stuff goes here
public void createGUI() {
/* allows the three parts (top, middle and right)
* to be made through (north, center and right) */
setLayout(new BorderLayout(20,20));
// setting the background colour
bgColour = new Color(190, 186, 221); // makes the sky blue colour for the background.
setBackground(bgColour);
// now putting a panel for the east side
eastPanel = new JPanel();
eastPanel.setBackground(bgColour);
eastPanel.setLayout(new BorderLayout(8, 8));
eastPanel.setPreferredSize(new Dimension(100, 280));
logoPanel = new JPanel();
logoPanel.setBackground(Color.WHITE);
logoPanel.setPreferredSize(new Dimension(100, 100));
logoPanel.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.green));
eastPanel.add(logoPanel, "North");
livesPanel = new JPanel();
livesPanel.setBackground(Color.WHITE);
livesPanel.setPreferredSize(new Dimension(100, 100));
JLabel label2 = new JLabel("Lives go here");
livesPanel.add(label2);
eastPanel.add(livesPanel, "Center");
scorePanel = new JPanel();
scorePanel.setBackground(Color.WHITE);
scorePanel.setPreferredSize(new Dimension(100, 80));
JLabel label3 = new JLabel("Scores go here");
scorePanel.add(label3);
eastPanel.add(scorePanel, "South");
add(eastPanel, "East");
tablePanel = new JPanel();
tablePanel.setBackground(bgColour);
tablePanel.setPreferredSize(new Dimension(200, 280));
add(tablePanel, "Center");
scrollTextPanel = new JPanel();
scrollTextPanel.setPreferredSize(new Dimension(300, 20));
scrollTextPanel.setBackground(Color.WHITE);
scrollTextPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(scrollTextPanel, "North");
}
@Override
public void paintComponent(Graphics g) {
System.out.println("paintComponent");
super.paintComponent(g);
g.setColor(Color.black);
g.drawImage(logo, 5, 5, 90, 90, this);
g.drawLine(0, 0, 300, 300); // for testing, does not work
}
// a little useful method for handling loading of images and stuff
public BufferedImage loadImage(String filename) {
BufferedImage image = null;
try {
URL url = new URL(pb.getCodeBase(), "images/" filename);
image = ImageIO.read(url);
} catch (IOException e) {
// do NOT ignore exceptions in broken code.
}
return image;
}
}
Комментарии:
1. Привет @Andrew Thompson, спасибо за это. Итак, вы говорите, что думаете / думали, что это был мой метод LoadImage? Я попробовал пару перестановок в нем, но попробую эту, если вы думаете, что это поможет.
2. Нет. Удалите аргументы первого вызова
BorderLayout
конструктора и проверьте разницу. Это должно привести к тому, что частично показанное изображение / строка снова исчезнет. Просто еще в сторону. Я сопротивлялся изменению большинстваsetPreferredSize()
вызовов, но обратите внимание, что лучше удалить их и решить, как правильно настроить графический интерфейс.