setOpaque (истина / ложь); Джава - PullRequest
12 голосов
/ 16 марта 2010

В Java2D, когда вы используете setOpaque, я немного запутался в том, что делает true и false.

Например, я знаю, что в Swing Opaque означает, что при рисовании Swing не будет рисовать то, что находится за компонентом. Или это назад? Какой это?

Спасибо

Ответы [ 3 ]

46 голосов
/ 16 марта 2010

Короткий ответ на ваш вопрос заключается в том, что «непрозрачный» на английском языке определяется как полностью непрозрачный. Поэтому непрозрачный компонент - это тот, который закрашивает весь прямоугольник, и каждый пиксель вовсе не является прозрачным.

Тем не менее, API непрозрачности компонента Swing - это один из тех неправильно разработанных и, следовательно, часто неправильно используемых API.

Важно понимать, что isOpaque - это контракт между системой Swing и конкретным компонентом. Если он возвращает true, компонент гарантирует непрозрачную прорисовку каждого пикселя своей прямоугольной области. Этот API должен быть абстрактным, чтобы все авторы компонентов могли его рассмотреть. API isOpaque используется системой рисования Swing для определения того, должна ли область, покрываемая данным компонентом, быть окрашенной для компонентов, которые перекрывают его и которые находятся за ним , включая компоненты Тара и предки. Если компонент возвращает true для этого API, система Swing может оптимизировать рисование, чтобы ничего не рисовать в этой области, пока не будет вызван метод рисования конкретного компонента.

Из-за договорного значения isOpaque API setOpaque не должен существовать , поскольку для любого внешнего вызова действительно неправильно вызывать setOpaque, поскольку, в свою очередь, внешняя вещь может ' не знаю, будет ли рассматриваемый компонент (или даже может) соблюдать его. Вместо этого isOpaque должен был быть переопределен каждым конкретным компонентом, чтобы возвращать, является ли он фактически непрозрачным, учитывая его текущие свойства.

Поскольку setOpaque API действительно существует, многие компоненты неправильно реализовали его (вполне понятно), чтобы определить, будут ли они рисовать свой "фон" (например, JLabel и JPanel, заполняющие их фоновый цвет). В результате у пользователей API создается впечатление, что setOpaque управляет диском, должен ли этот фон рисовать, но это не так.

Кроме того, если, скажем, вы хотите нарисовать JLabel с полупрозрачным фоном, вам нужно установить цвет фона с альфа-значением и сделать setOpaque (true), но это не совсем непрозрачно - это полупрозрачный ; Компоненты, стоящие за ним, все еще должны рисовать, чтобы компонент правильно отображался.

Эта проблема была раскрыта в значительной степени с новым Nimbus Look & Feel в Java 6. Существует множество сообщений об ошибках, связанных с прозрачными компонентами, поданными против Nimbus (см. Вопрос о переполнении стека Java Nimbus LAF с прозрачными текстовыми полями ). Ответ команды разработчиков Nimbus таков:

Это проблема [оригинального] дизайна Swing и его запутанности в течение многих лет. Проблема в том, что setOpaque (false) имеет [побочный эффект] в [существующих] LAF, а именно в скрытии фона, который на самом деле не предназначен для [предназначенного]. [Подразумевается], что компонент может иметь прозрачные части, и [Swing] должен закрасить родительский компонент за ним.

Итак, в итоге, вы не должны использовать setOpaque. Если вы используете его, имейте в виду, что комбинация некоторых Look & Feels и некоторых компонентов может сделать «удивительные» вещи. И, в конце концов, на самом деле нет правильного ответа.

1 голос
/ 16 марта 2010

javadoc говорит: Если true, компонент закрашивает каждый пиксель в пределах своих границ. В противном случае компонент может не закрасить некоторые или все свои пиксели, позволяя просвечивать нижележащие пиксели.

попробуйте этот пример программы тоже ... http://www.java2s.com/Code/JavaAPI/javax.swing/JPanelsetOpaquebooleanisOpaque.htm

0 голосов
/ 07 марта 2015

Я думаю, что также необходимо добавить следующее:

Термин непрозрачный имеет различные значения в Java 2D и в Swing.

В Java непрозрачность 2D - это концепция рендеринга. Это комбинация альфа-значения и режим Composite. Это степень какие цвета пикселей должны быть смешаны с пикселем значения уже присутствуют. Например, мы рисуем полупрозрачный прямоугольник над существующей овальной формой. Поэтому овал частично видимый Эту концепцию часто сравнивают со светом идет через стакан или воду.

В Swing непрозрачный компонент закрашивает каждый пиксель в пределах своего прямоугольные границы. Непрозрачный компонент рисует только подмножество его пиксели или вообще нет, что позволяет пикселям под ним показать до конца. Непрозрачное свойство было установлено из соображений эффективности; свинг не нужно красить области за непрозрачными компонентами.

Источник: Java-документы и отвратительные клиенты

package com.zetcode;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import static javax.swing.SwingConstants.CENTER;
import net.miginfocom.swing.MigLayout;

class DrawingPanel extends JPanel {

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        doDrawing(g);
    }

    private void doDrawing(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(Color.green);
        g2d.fillOval(20, 20, 100, 100);
        g2d.setColor(Color.blue);
        g2d.setComposite(AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, 0.1f));
        g2d.fillRect(0, 0, 150, 150);
    }
}

class MyLabel extends JLabel {

    public MyLabel(String text) {
        super(text, null, CENTER);
    }

    @Override
    public boolean isOpaque() {
        return true;
    }
}

public class OpaqueEx2 extends JFrame {

    public OpaqueEx2() {

        initUI();
    }

    private void initUI() {

        JLabel lbl1 = new JLabel("Java 2D opacity");
        JLabel lbl2 = new JLabel("Swing opaque");

        DrawingPanel dpanel = new DrawingPanel();

        MyLabel mylbl = new MyLabel("isOpaque()");
        mylbl.setBackground(Color.decode("#A9A9A9"));

        createLayout(lbl1, lbl2, dpanel, mylbl);

        setTitle("Opaque");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void createLayout(JComponent... arg) {

        JPanel pnl = new JPanel(new MigLayout("ins 10"));

        pnl.add(arg[0], "w 150");
        pnl.add(arg[1], "w 150, wrap");
        pnl.add(arg[2], "w 150, h 150");
        pnl.add(arg[3], "w 150, h 150");

        add(pnl);
        pack();
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                OpaqueEx2 ex = new OpaqueEx2();
                ex.setVisible(true);
            }
        });
    }
}

В примере кода у нас есть два компонента. Компонент слева представляет собой панель, которая использует AlphaComposite для рисования высокопрозрачного прямоугольника над овалом. Компонент справа является меткой. Этикетки непрозрачны в большинстве случаев. Мы перезаписываем метод метки isOpaque(), чтобы установить серый фон.

Opaque explained

...