New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Swt doesn't allow transparent backgrounds #79
Comments
|
@wasnotrice Sorry, I've not dived into #59 (also not reviewed your code at #78) yet. But, how about require 'java'
require 'swt'
$display = display = Swt::Widgets::Display.new
white = display.getSystemColor(Swt::SWT::COLOR_WHITE)
red = display.getSystemColor(Swt::SWT::COLOR_RED)
green = display.getSystemColor(Swt::SWT::COLOR_GREEN)
shell = Swt::Widgets::Shell.new display, Swt::SWT::SHELL_TRIM
shell.setBackground white
shell.addListener Swt::SWT::Close, proc{Swt.display.dispose}
cs1 = Swt::Widgets::Composite.new shell, Swt::SWT::TRANSPARENT
cs1.setSize 200, 200
blk = proc do |e|
gc = e.gc
gc.setBackground green
gc.fillOval 25, 25, 100, 100
end
cs1.add_paint_listener(blk)
cs2 = Swt::Widgets::Composite.new cs1, Swt::SWT::TRANSPARENT
cs2.setSize 150, 150
cs2.setLocation 50, 50
blk = proc do |e|
gc = e.gc
gc.setBackground red
gc.fillOval 25, 25, 100, 100
end
cs2.add_paint_listener(blk)
b = Swt::Widgets::Button.new cs1, Swt::SWT::PUSH
b.setText 'button'
b.pack
class Anim
def initialize &blk
@blk = blk
end
def run
@blk.call
$display.timerExec 100, self
end
end
i = 0
a = Anim.new{i+=1; b.setLocation i, i; cs1.redraw}
display.timerExec 100, a
shell.pack
shell.open
Swt.event_loop{Swt.display.isDisposed} |
|
Ahhh,... sad. :( |
|
Hmmm. That might work. I haven't tried SWT::TRANSPARENT on Linux. But this kind of defeats the purpose of using a cross-platform framework :( |
|
Yeah, but there is no perfect cross-platform framework. So, if SWT::TRANSPARENT works on Linux, I think that is a acceptable workaround for now. Okay now, back to your first question. We have to make a decision on which way to go.
Note: In the last case, it's difficult to add scrollbars for each Flow/Stack areas. |
|
On my Ubuntu box, @ashbb's snippet looks like this. |
|
@jrgifford mine is similar except I get trails (this is ubuntu 11.04 in a Parallels VM). So TRANSPARENT doesn't work on OS X or on Linux. Let's look at NO_BACKGROUND again:
Can we work with this? What if we make sure that cs1 paints its whole area, like this? require 'java'
require 'swt'
$display = display = Swt::Widgets::Display.new
white = display.getSystemColor(Swt::SWT::COLOR_WHITE)
red = display.getSystemColor(Swt::SWT::COLOR_RED)
green = display.getSystemColor(Swt::SWT::COLOR_GREEN)
shell = Swt::Widgets::Shell.new display, Swt::SWT::SHELL_TRIM
shell.setBackground white
shell.addListener Swt::SWT::Close, proc{Swt.display.dispose}
#cs1 = Swt::Widgets::Composite.new shell, Swt::SWT::TRANSPARENT
cs1 = Swt::Widgets::Composite.new shell, Swt::SWT::NO_BACKGROUND
cs1.setSize 200, 200
blk = proc do |e|
gc = e.gc
gc.setBackground white
gc.fill_rectangle 0, 0, 200, 200
gc.setBackground green
gc.fillOval 25, 25, 100, 100
end
cs1.add_paint_listener(blk)
cs2 = Swt::Widgets::Composite.new cs1, Swt::SWT::NO_BACKGROUND
cs2.setSize 150, 150
cs2.setLocation 50, 50
blk = proc do |e|
gc = e.gc
gc.setBackground red
gc.fillOval 25, 25, 100, 100
end
cs2.add_paint_listener(blk)
b = Swt::Widgets::Button.new cs1, Swt::SWT::PUSH
b.setText 'button'
b.pack
class Anim
def initialize &blk
@blk = blk
end
def run
@blk.call
$display.timerExec 100, self
end
end
i = 0
a = Anim.new do
i+=1
b.setLocation i, i
cs1.redraw
shell.redraw(0, 0, shell.getSize.x, shell.getSize.y, true)
shell.update
end
display.timerExec 100, a
shell.pack
shell.open
Swt.event_loop{Swt.display.isDisposed}This removes the trails for me (but not the background of cs2). Also works on OS X. See this video. |
|
@wasnotrice @jrgifford I just realized |
|
The snippet that @wasnotrice has above looks like this on 12.04. And I'm not quite sure what to change it to what @ashbb wants us to test. :P |
|
@jrgifford Oh, sorry my poor explanation. xx-P What I wanted to say is:
cs1 = Swt::Widgets::Composite.new shell, Swt::SWT::NO_BACKGROUND | Swt::SWT::TRANSPARENT # line 14
cs2 = Swt::Widgets::Composite.new cs1, Swt::SWT::NO_BACKGROUND | Swt::SWT::TRANSPARENT # line 26 |
|
@ashbb When I use NO_BACKGROUND and TRANSPARENT, I don't notice any difference on OS X or linux from my previous version. Works well OS X. Works on Linux except that red circle has a gray background. |
|
I found this article that uses Canvas with an image to get a transparent background. I wanted to experiment by changing our example from cs1 = Swt::Widgets::Canvas.new shell, Swt::SWT::NO_BACKGROUND | Swt::SWT::TRANSPARENT
# and later
cs2 = Swt::Widgets::Canvas.new cs1, Swt::SWT::NO_BACKGROUND | Swt::SWT::TRANSPARENTBut I get this error: What am I doing wrong? |
|
First, thank you for the confirmaion.
Glad to hear that. Then we can get a composite container with transparent background without using But,...
Ah,... sad. :( Second, look at C:\jruby\lib\ruby\gems\1.8\gems\swt-0.12\lib\swt\full.rb. module Swt::Widgets
import org.eclipse.swt.widgets.Canvas
endAfter adding the above snippet, our example works with Canvas as same as Composite on my Windows 7. |
|
@ashbb Thanks! But no luck so far on Linux :( |
|
@wasnotrice and folks, Well, it seems that there is no solution for Linux to make Swt::Composite with transparent background. So, how about the following? class ShoesComposite < Swt::Widgets::Composite
def initialize *cs
@cs = cs[0]
super
end
def add_paint_listener blk
@cs.add_paint_listener blk
end
end
cs1 = Swt::Widgets::Composite.new shell, Swt::SWT::NULL # implicit shoes top-slot
cs2 = ShoesComposite.new cs1, Swt::SWT::NULL # Shoes Flow or Stack
This is the same story as Purple Shoes. Although the implementation is very different. |
|
@ashbb I haven't played with this code yet, but do you think this allows us to do the layering that Shoes requires? By controlling the order of the paint callbacks, maybe? |
|
@ashbb OK, now I've played with the code ;) But I can't get the button to slide in between the circles (it just passes over them). I made Here's what I've got: require 'java'
require 'swt'
module Swt
include_package 'org.eclipse.swt.graphics'
include_package 'org.eclipse.swt.events'
end
class ShoesComposite
def initialize *cs
@cs = cs[0]
end
def setSize(w,h)
@width, @height = w, h
end
def setLocation(x,y)
@x, @y = x, y
end
def add_paint_listener blk
# Wrap the block so the paint callback happens at the right (x,y)
wrapped_blk = proc do |e|
gc = e.gc
transform = ::Swt::Transform.new(::Swt.display)
transform.translate @x, @y
gc.transform = transform
blk.call(e)
transform.dispose
end
@cs.add_paint_listener wrapped_blk
end
end
$display = display = Swt::Widgets::Display.new
white = display.getSystemColor(Swt::SWT::COLOR_WHITE)
red = display.getSystemColor(Swt::SWT::COLOR_RED)
green = display.getSystemColor(Swt::SWT::COLOR_GREEN)
shell = Swt::Widgets::Shell.new display, Swt::SWT::SHELL_TRIM
shell.setBackground white
shell.addListener Swt::SWT::Close, proc{Swt.display.dispose}
# Implicit top slot
cs0 = Swt::Widgets::Composite.new shell, Swt::SWT::NULL
cs0.setSize 200, 200
# Slot 1 (green circle)
cs1 = ShoesComposite.new cs0
blk = proc do |e|
gc = e.gc
gc.setBackground white
gc.fill_rectangle 0, 0, 200, 200
gc.setBackground green
gc.fillOval 25, 25, 100, 100
end
cs1.add_paint_listener(blk)
# Slot 2 (red circle)
cs2 = ShoesComposite.new cs0
cs2.setSize 150, 150
cs2.setLocation 50, 50
blk = proc do |e|
gc = e.gc
gc.setBackground red
gc.fillOval 25, 25, 100, 100
end
cs2.add_paint_listener(blk)
# Button
b = Swt::Widgets::Button.new cs0, Swt::SWT::PUSH
b.setText 'button'
b.pack
# Animation
class Anim
def initialize &blk
@blk = blk
end
def run
@blk.call
$display.timerExec 100, self
end
end
i = 0
a = Anim.new do
i+=1
b.setLocation i, i
shell.redraw
end
display.timerExec 100, a
shell.pack
shell.open
Swt.event_loop{Swt.display.isDisposed}Can you make the button go in between the circles? |
|
@wasnotrice Awesome! Shoes.app do
nostroke
oval 0, 0, 100, 100, fill: red
stack left: 50, top: 50 do
oval 0, 0, 100, 100, fill: green
end
b = button 'button'
animate do |i|
b.move i, i
end
endOkay, next up is:
Umm,... I also got an error. But that was "ArgumentError: wrong number of arguments for constructor". So I edited your code like this. Then it worked. class ShoesComposite < Swt::Widgets::Composite
def initialize *cs
@cs = cs[0]
super cs[0], Swt::SWT::NULL
end |
|
Man you guys are working like crazy, thank you so much! Tried out the last snippet from @wasnotrice with and without the modification by @ashbb - both work fine on my Linux distribution (Linux Mint Debian Edition with Cinnamon as the desktop manager). Great work! |
|
Just to complicate things :P Here's a version of this snippet written with Qt on OS X and Linux. Qt seems _much_ more complete than Swt. This code is running on MRI 1.9.3, which gives up some JRuby benefits. require 'Qt'
class Color
def self.white
Qt::Color.new(255, 255, 255)
end
def self.red
Qt::Color.new(255, 0, 0)
end
def self.green
Qt::Color.new(0, 255, 0)
end
end
class Slot < Qt::Widget
def initialize(parent)
super
@paint_blocks = []
end
def paint(&block)
@paint_blocks << block
end
def paintEvent(event)
painter = Qt::Painter.new(self)
painter.setRenderHint Qt::Painter::Antialiasing
@paint_blocks.each do |b|
b.call(painter)
end
painter.end
end
end
class ShoesButton < Qt::PushButton
slots :move
def move()
self.setGeometry Qt::Rect.new(Qt::Point.new(self.x + 1, self.y + 1), self.size)
end
end
app = Qt::Application.new([])
window = Qt::Widget.new
palette = window.palette
palette.setColor(Qt::Palette::Window, Color.white)
window.palette = palette
# Green circle
slot1 = Slot.new(window)
slot1.setGeometry 0, 0, 200, 200
slot1.paint do |painter|
painter.setBrush(Qt::Brush.new Color.green)
painter.setPen(Qt::NoPen)
painter.setOpacity 0.5
painter.drawEllipse(25, 25, 100, 100)
end
# Button
button = ShoesButton.new "Button", window
# Red circle
slot2 = Slot.new(window)
slot2.setGeometry 50, 50, 200, 200
slot2.paint do |painter|
painter.setBrush(Qt::Brush.new Color.red)
painter.setPen(Qt::NoPen)
painter.setOpacity 0.5
painter.drawEllipse(25, 25, 100, 100)
end
# Animation
timer = Qt::Timer.new(window)
timer.connect(timer, SIGNAL('timeout()'), button, SLOT('move()'))
timer.start 100
window.show
window.raise
app.exec |
|
Cool! |
|
@ashbb It would surprise me if it were that easy, a short google search turned up this promising stackoverflow discussion However if you are to install WT beforehand (not only the gem) take caution, the first option is awfully big, the libraries are farther down on the download page |
|
@PragTob Oh, umm,... I can accept some annoying install steps for developing Shoes 4, but may not be able to accept for using Shoes 4... |
|
@ashbb looks like it should be as easy as I have been recording steps to get setup with OS X and Linux at my shoes-qt repo. Also very simple.
Yes, we should be conscious of this. We would have to bundle Qt with Shoes, like we have been bundling cairo and pango with Shoes3. There are Java bindings for Qt, at the Qt-Jambi project, so it seems possible to run Qt from JRuby. But I could not get these to work on my machine, and they are running at least a version behind the Qt project, so might not be a reliable resource. Straight Qt was very simple to setup. |
|
Have you guys considered doing this by drawing a bunch of lines ontop of each other until they form circles? I realize how assinine that sounds, but you have to do something similar in HTML5 Canvas if you want to draw circles. <script>
context.arc(x, y, radius, 0 , 2 * Math.PI, false);
</script>(Yes, the only way to draw a circle with the canvas api is by drawing an arc... sigh) |
|
Drawing the circle is not the problem. The problem is that swt widgets all have opaque backgrounds on Linux :( @ashbb just happened to use a circle in his snippet exploring the problem :) |
|
You mean that the backgrounds aren't transparent? |
|
Yep like that, take a look at the screenshot |
|
About the topic of Qt - Qt is indeed pretty complete (I'm currently working with Qt at university, unfortunately with C++ :-/) and the docs are some of the best I've ever seen. The question if we would really want to switch the backend or start the development of a new backend in parallel to SWT. Giving up JRuby would be hard though... well no matter what, I like Qt as a possible backend for shoes in the future :-) |
|
Oops, I didn't read the answer. xx-P Now the above @wasnotrice's snippet works fantastic on my Windows 7 with Ruby 1.9.3. Awesome! |
|
@ashbb Great! :) So...now we have some big decisions to make. On the ML? |
|
Yep I'm all for ML. I guess/hope more people notice it that way... however we should also make an issue here referring to the ML (or the other way around, so both channels get the news) |
|
@PragTob In that case "draw circles using lines" will solve that problem. Are there really any other elements where this is an issue? |
|
@davorb The problem is rather that we wanted to use Swt::Composite in order to implement stack and flow, which have to be transparent by definition - so this is a huge drawback. |
|
@PragTob Ah, I see... Thanks for explaining it to me. |
|
@ozpos Thanks for the information. That's interesting. But we may need another solution, because we are finding how to inprement Set::Composite with transparent background, not Swt::Label. |
|
You guys think doing something similar to what this guy (Alun) is suggesting might work? http://www.eclipsezone.com/eclipse/forums/t23689.html |
|
@davorb We don't want to see the background of Composite through the controls. We want to make the background of Composite itself transparent. So, I think we need an other solution... |
|
Closing as fixed. See #103. |


I have been working on solving
#movein #59 (see code at #78) and ran into this problem. Swt doesn't allow transparent backgrounds. I have been looking into this for a few days now, and can't seem to figure it out. So here are questions for you all:The text was updated successfully, but these errors were encountered: