Хотя ваш вопрос немного расплывчатый, я «думаю», что он идет по пути того, о чем вы просите ...
public class ImageView extends JComponent {
protected static final Dimension DEFAULT_SIZE = new Dimension(480, 320);
private BufferedImage mImage;
public ImageView() {
setBackground(Color.WHITE);
}
public ImageView(int width, int height) {
this();
mImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
clear();
}
public BufferedImage getImage() {
return mImage;
}
public void setImage(BufferedImage image) {
mImage = image;
}
public void clear() {
if (mImage == null) {
return;
}
Graphics g = mImage.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, mImage.getWidth(), mImage.getHeight());
g.dispose();
}
@Override
public Dimension getPreferredSize() {
return mImage == null ? DEFAULT_SIZE : new Dimension(mImage.getWidth(), mImage.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (mImage == null) {
return;
}
//g.setColor(Color.white);
//g.fillRect(0, 0, getWidth(), getHeight());
int x = (getWidth() - mImage.getWidth()) / 2;
int y = (getHeight() - mImage.getHeight()) / 2;
g.drawImage(mImage, x, y,this);
}
}
Обычно, когда mImage
равен null
, он возвращает предварительно определенное DEFAULT_SIZE
компонента (а также не рисует изображение)
Нет, я хочу получить размер, который менеджер родительского макета установит для моего компонента. Если мой компонент заполнит все доступное пространство, которое было предоставлено менеджером макета, я хочу получить размер этого пространства. То есть Я могу установить в конструкторе по умолчанию размер изображения 300x300, но мой компонент будет иметь размер 400x300, потому что менеджер компоновки позволял заполнять большее пространство. Как я могу получить размер, который будет иметь мой компонент после запуска.
До тех пор, пока компонент не будет физически размещен родительским контейнером, нет способа узнать, какого размера он ему даст. Вы можете отслеживать изменения на setBounds
, но я склонен находить invalidate
лучший выбор (ИМХО).
Проблема в том, что все эти методы можно вызывать несколько раз в быстрой последовательности, поэтому, если вы выполняете операции, которые занимают время или требуют большого объема памяти, лучше использовать какой-то «отложенный обратный вызов». ", заставляя пройти необходимое количество времени, прежде чем выполнить требуемое действие.
Я склонен использовать Swing Timer
, чтобы сделать это, просто он вызывает ActionListener
на EDT, делая безопасным обновление пользовательского интерфейса из
public class ImageView extends JComponent {
protected static final Dimension DEFAULT_SIZE = new Dimension(480, 320);
private BufferedImage mImage;
private Timer invalidationTimer;
public ImageView() {
setBackground(Color.WHITE);
invalidationTimer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stateInvalidated();
}
});
invalidationTimer.setRepeats(false);
}
public ImageView(int width, int height) {
this();
mImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
clear();
}
@Override
public void invalidate() {
super.invalidate();
invalidationTimer.restart();
}
protected void stateInvalidated() {
System.out.println(getWidth() + "x" + getHeight());
}
public BufferedImage getImage() {
return mImage;
}
public void setImage(BufferedImage image) {
mImage = image;
}
public void clear() {
if (mImage == null) {
return;
}
Graphics g = mImage.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, mImage.getWidth(), mImage.getHeight());
g.dispose();
}
@Override
public Dimension getPreferredSize() {
return mImage == null ? DEFAULT_SIZE : new Dimension(mImage.getWidth(), mImage.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (mImage == null) {
return;
}
//g.setColor(Color.white);
//g.fillRect(0, 0, getWidth(), getHeight());
int x = (getWidth() - mImage.getWidth()) / 2;
int y = (getHeight() - mImage.getHeight()) / 2;
g.drawImage(mImage, x, y, this);
}
}