Проблемы градиента в Java
в моей программе я хотел иметь полупрозрачный белый до прозрачного градиента на моем JFrame, чтобы наложить желтый фон. Это отлично работает, и он должен быть белым для прозрачности из-за того, как мои настройки для программы работают для пользователя. Однако, когда я беру программу в колледж (JRE7 в мой JRE6), градиент становится белым, чтобы затем черноватым, а затем прозрачным... Это не так плохо, пока вы не начнете увеличивать непрозрачность белого цвета... есть ли что-то, что я могу исправить? это?
вот соответствующий код из верхней части моего кода форму.
public class DictionaryGUI extends JFrame
{
protected JPanel pGradientPane;
//Interface gradient specification
private Color pInterfaceColour = new Color(255, 245, 62);
protected int iDegreeWhite = 180
protected int iDegreeBlack = 0
DictionaryGUI(int iWidth, int iHeight)
{
/*General definitions*/
super(String.format("French Verb Conjugator - Version %s", MainLauncher.version));
setSize(iWidth, iHeight);
new Menu(this);
this.iWidth = iWidth;
this.iHeight = iHeight;
getContentPane().setBackground(pInterfaceColour);
pGradientPane = new JPanel(new GridBagLayout())
{
private static final long serialVersionUID = 1L;
protected void paintComponent(Graphics pGraphics)
{
Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
pGraphicsGradientRender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0, iDegreeBlack));
pGraphicsGradientRender.setPaint(pGradient);
pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(pGraphics);
}
};
pGradientPane.setOpaque(false);
pGradientPane.setPreferredSize(new Dimension(iWidth - 16, iHeight - 62));
/*components added to pGradientPane here!*/
add(pGradientPane);
}
и mainclass хорошо:
public class MainLauncher
{
static int iHeight = 400;
static int iWidth = 730;
static String version = "0A3B6";
public static void main(String[] args)
{
try
{
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
{
if ("Nimbus".equals(info.getName()))
{
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {e.printStackTrace();}
DictionaryGUI window = new DictionaryGUI(iWidth, iHeight);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationByPlatform(true);
window.setVisible(true);
}
это просто какая-то разница между JRE6 и JRE7? должен ли я сделать нижний цвет белым? (был черный, если люди хотят потемнеть цвет внизу.)
Я могу опубликовать некоторые скриншоты tommorrow, если кому-то нужно их....
спасибо Джейми!--3-->
EDIT: Я изменил второй (прозрачный) цвет в градиенте на белый, и это исправляет проблему. Однако меня все еще беспокоит, почему прозрачный черный цвет просвечивает посередине? это должно быть как-то связано с JRE7, потому что именно там это происходит... возможно, они что-то изменили с тем, как работает прозрачность в градиентах. Кто-нибудь знает как устранить эта проблема при сохранении черного цвета?
5 ответов
проблема с кодом заключается в следующем:
GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0, iDegreeBlack));
должно быть:
GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(255, 245, 62, iDegreeWhite));
оглядываясь на ваш вопрос, я вижу, что вы в основном нашли решение , но это немного отличается. Вот почему:
при смешивании цветов в градиенте, ваше смешивание всех аспектов цвета: RBGA
вы видите, пока вы не достигнете полного второго цвета, вы смешиваете черноту в градиент цвета и это смешивание не будет на полном прозрачность. Таким образом, 20% пути вниз по странице, у вас будет этот цвет: 204,204,204,144 (это 80% Белого, 20% черного и 56% непрозрачного).
самое простое решение-полностью избежать прозрачности, если вы его не используете - просто смешайте от светло-желтого вверху до темно-желтого внизу. Это тоже требует меньше ресурсов.
но поскольку вы используете прозрачность, решение, которое я предоставил, также использует прозрачность. Ты будешь сливаться с белым. желтый с использованием постоянной прозрачности.
Если вы смешиваете от белого до белого (прозрачного), у вас будет та же проблема, что и раньше, только с белым (который будет менее заметен, поскольку это один из цветов, которые вы используете): градиент будет иметь белую "полосу", пока второй цвет не достигнет полной прозрачности.
что касается того, почему он действует по-разному на разных JVMs, я бы предположил, что Oracle, возможно, изменил способ смешивания alpha. Кажется, что лучшая поддержка alpha быть чем-то, над чем они работали некоторое время, и это логичный шаг в этом направлении. У меня нет никаких доказательств этого утверждения, хотя - это просто основано на других изменениях, которые я видел с alpha (например, прозрачное окно).
редактировать Это SSCCE Демос обе проблемы и решения:
import java.awt.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
public class TransparencyDemo extends Box{
protected JPanel pGradientPane;
//Interface gradient specification
private Color pInterfaceColour = new Color(255, 245, 62);
protected int iDegreeWhite = 180;
protected int iDegreeBlack = 0;
public TransparencyDemo() {
super(BoxLayout.X_AXIS);
setOpaque(true);
//Incorrect Solution
pGradientPane = new JPanel(new GridBagLayout())
{
private static final long serialVersionUID = 1L;
protected void paintComponent(Graphics pGraphics)
{
Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
pGraphicsGradientRender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0, iDegreeBlack));
pGraphicsGradientRender.setPaint(pGradient);
pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(pGraphics);
}
};
pGradientPane.setOpaque(false);
add(pGradientPane);
//Correct Solution
JPanel pGradientPane2 = new JPanel(new GridBagLayout())
{
private static final long serialVersionUID = 1L;
protected void paintComponent(Graphics pGraphics)
{
Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
pGraphicsGradientRender.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(255, 245, 62, iDegreeWhite));
pGraphicsGradientRender.setPaint(pGradient);
pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(pGraphics);
}
};
pGradientPane2.setOpaque(false);
add(pGradientPane2);
setBackground(pInterfaceColour);
}
public static void main(String[] args){
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TransparencyDemo());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
вот моя версия вашего кода sscce:
import java.awt.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
public class MainLauncher {
static int iHeight = 400;
static int iWidth = 730;
static String version = "0A3B6";
public static void main(String[] args) {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
DictionaryGUI window = new DictionaryGUI(iWidth, iHeight);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationByPlatform(true);
window.setVisible(true);
}
}
class DictionaryGUI extends JFrame {
protected JPanel pGradientPane;
// Interface gradient specification
private Color pInterfaceColour = new Color(255, 245, 62);
protected int iDegreeWhite = 180;
protected int iDegreeBlack = 0;
DictionaryGUI(int iWidth, int iHeight) {
/* General definitions */
super(String.format("French Verb Conjugator - Version %s",
MainLauncher.version));
setSize(iWidth, iHeight);
getContentPane().setBackground(pInterfaceColour);
pGradientPane = new JPanel() {
private static final long serialVersionUID = 1L;
protected void paintComponent(Graphics pGraphics) {
Graphics2D pGraphicsGradientRender = (Graphics2D) pGraphics;
pGraphicsGradientRender.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint pGradient = new GradientPaint(0, 0, new Color(255,
255, 255, iDegreeWhite), 0, getHeight(), new Color(0, 0, 0,
iDegreeBlack));
pGraphicsGradientRender.setPaint(pGradient);
pGraphicsGradientRender.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(pGraphics);
}
};
pGradientPane.setOpaque(false);
pGradientPane.setPreferredSize(new Dimension(iWidth - 16, iHeight - 62));
/* components added to pGradientPane here! */
add(pGradientPane);
}
}
но опять же это не показывает вашу проблему. Я предполагаю, что ваша проблема заключается в использовании прозрачных фонов с Swing GUI, где артефакты рисования не исправлены полностью. Если да, пожалуйста, прочитайте, что Роб Камик должен сказать об этом в своем блоге:Фоны С Прозрачностью
Я предполагаю, что речь идет о "графическом конвейере", который используется на разных компьютерах.
Java имеет несколько разных конвейеров, вот некоторая информация о них.
на моем компьютере я могу использовать конвейер X11 или конвейер OpenGL. С трубопроводом X11 происходит темнота; на OpenGL это не так.
в Windows вы можете выбрать один из 3 различных трубопроводов, и даже тогда (глядя на ссылку выше), может быть различия.
Я не могу сразу представить, какова конфигурация вашей школы и почему она отличается, но вы можете попытаться исследовать.
вы можете подать эту разницу как ошибку.
У меня есть fatamorgana, я уверен, что GradientPaint темнее и темнее и темнее, phaaa crazy eye illusion, brrrr
//http://stackoverflow.com/questions/13748810/gradient-problems-in-java/13806210#comment18995490_13806210
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
public class MainLauncher {
private JFrame window = new JFrame();
public MainLauncher() {
GradientPane pane = new GradientPane();
pane.setLayout(new GridLayout(6, 4, 15, 15));
for (int i = 1; i <= 24; i++) {
pane.add(createButton(i));
}
pane.setOpaque(false);
window.add(pane);
RepaintManager.setCurrentManager(new RepaintManager() {
@Override
public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
Container con = c.getParent();
while (con instanceof JComponent) {
if (!con.isVisible()) {
return;
}
if (con instanceof GradientPane) {
c = (JComponent) con;
x = 0;
y = 0;
w = con.getWidth();
h = con.getHeight();
}
con = con.getParent();
}
super.addDirtyRegion(c, x, y, w, h);
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationByPlatform(true);
window.setSize(400, 300);
//window.pack();
window.setVisible(true);
}
private JButton createButton(final int text) {
JButton button = new JButton(Integer.toString(text));
return button;
}
class GradientPane extends JPanel {
private static final long serialVersionUID = 1L;
private final int h = 150;
private BufferedImage img = null;
private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB);
public GradientPane() {
paintBackGround(new Color(150, 250, 150));
}
public void paintBackGround(Color g) {
Graphics2D g2 = shadow.createGraphics();
g2.setPaint(g);
g2.fillRect(0, 0, 1, h);
g2.setComposite(AlphaComposite.DstIn);
g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h, new Color(0.1f, 0.8f, 0.8f, 0.5f)));
g2.fillRect(0, 0, 1, h);
g2.dispose();
}
@Override
public void paintComponent(Graphics g) {
if (img == null || img.getWidth() != getWidth() || img.getHeight() != getHeight()) {
img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2 = img.createGraphics();
super.paintComponent(g2);
Rectangle bounds = this.getVisibleRect();
g2.scale(bounds.getWidth(), -1);
g2.drawImage(shadow, bounds.x, -bounds.y - h, null);
g2.scale(1, -1);
g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h, null);
g2.dispose();
g.drawImage(img, 0, 0, null);
}
}
public static void main(String[] args) {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MainLauncher ml = new MainLauncher();
}
});
}
}
Как отметил Ник, проблема в том, что вы используете прозрачный черный, а не прозрачный белый. Таким образом, полупрозрачные цвета-это оттенок между белым и черным.
попробуйте заменить эту строку в коде:
GradientPaint pGradient = new GradientPaint(0, 0, new Color(255, 255, 255, iDegreeWhite), 0, getHeight(), new Color(255, 255, 255, iDegreeBlack));