It looks like you're new here. If you want to get involved, click one of these buttons!
Hi Matthias,
I tried to use QT to generate a window. Below is my code. I created a icon on top tool bar, then the window can be created after pressing the icon. But the problem i met is that as i drag the winodw edge trying to adjust its size. When i keep doing this action around few seconds, the Klayout is crashed. Could you help clarify the cause ?? Many thanks.
Best regards,
Covalent
class MenuHandler < RBA::Action
def initialize( t, &action )
self.title = t
@action = action
end
def triggered
@action.call( self )
end
private
@action
end
class UI_Main
include RBA
def gen_ui
wdg = QWidget.new
wdg.setWindowTitle("Windows")
wdg.resize 350, 300
wdg.move 300, 300
wdg.show
vbox = QVBoxLayout.new
vbox1 = QVBoxLayout.new
hbox1 = QHBoxLayout.new
hbox2 = QHBoxLayout.new
windowlabel1 = QLabel.new("Windows")
edit = QTextEdit.new
edit.enabled = false
activate = QPushButton.new("Activate")
close = QPushButton.new("Close")
help = QPushButton.new("Help")
ok = QPushButton.new("OK")
vbox.addWidget(windowlabel1)
vbox1.addWidget(activate)
vbox1.addWidget(close, 0, 0x0020)
hbox1.addWidget(edit)
hbox1.addLayout(vbox1)
vbox.addLayout(hbox1)
hbox2.addWidget(help)
hbox2.addStretch
hbox2.addWidget(ok)
vbox.addLayout(hbox2, 1)
wdg.setLayout(vbox)
end
end
class UI_Test
def initialize
UI_Main.new.gen_ui
end
end
# ---------------------------------------------------------------------------
# Main application
app = RBA::Application.instance
mw = app.main_window
@menu_handler = MenuHandler.new("RBA test"){UI_Test.new}
mw.menu.insert_item("@toolbar.end", "rba_test", @menu_handler)
app.exec
Comments
Hi covalent,
I have used the Qt binding to do similar things. Looking at your code, there are two issues that come to my mind:
You don't need to call
app.exec
at the end. This seems to be a pattern in creating standalone Qt applications but in our case, the application (i.e. KLayout) is already running.Although I don't think I ever saw it crashing, KLayout version 0.23 does have some focus issues with the Macro Development window when it is open. If you want to know more about it, I'd recommend reading about it here, the bottom line is that this issue seems to be fixed with KLayout version 0.24-python-eval which I can highly recommend. Keep in mind that you'll have to change some Qt constants in your code to make it work.
I was able to run your code (without the
app.exec
line) in version 0.23, but I had to close the Macro Development window in order to be able to resize your window.If this information doesn't solve your issue, could you also tell me which KLayout version you're running and on which platform (Windows, Linux...)?
Hi friendfx,
Thanks for your reply. I use 0.23.4 on win7.
The reason i add app.exec in the end is that i don't use Macro Developement window to run this code. I use the way of klayout.exe -r $my_ruby_code_path to run it, so i have to use app.exec to call klayout main window.
I don't know if my problem is similar to yours. But if i changed my ui_content as simple as below. There won't be the problem i met before.
Hi covalent,
I am currently running version 0.23.10 under Win7. I just tried your code (including the
app.exec
line at the end) viaklayout -r Discussion611.lym
.Discussion611.lym is your complete code (copy-pasted into the Macro editor) from the first post, wrapped between
module Discussion611
andend
lines.This works perfectly for me, the button shows up and when I click it, the window opens and is resizable as expected.
UPDATE
...at least so I thought. I guess I wasn't resizing the window for long enough :-)
Strange. In the Task Manager, I can see that the memory consumption by klayout.exe increases while I am resizing the window and it doesn't go back down once I release the mouse button. I even tried several shorter resize durations, each one increasing the memory consumption.
And at some point, the GUI of the application freezes and I have to force-close it.
I also tried this with version 0.24-python-eval (had to replace your constant with
Qt::AlignTop
), same issue.UPDATE 2
Trying this on version r2739 on my Ubuntu VM actually crashed the program once I clicked the button, leading to a stack trace and the following message:
I also tried with the official Ubuntu 0.23.10 version, which let me click the button fine but the resize problem is the same as under windows - eventually causing a stacktrace ending with the same message as shown above. For reference, on my Ubuntu VM, KLayout seems to use Ruby version 1.9.3-p484 (x86_64-linux).
If I was in your shoes, the next thing I'd try would be
Hi friendfx,
Thanks for your test. I keep trying the find the cause. Btw, I also see the memory consumption problem.
Regareds,
covalent
Hi covalent,
I think the problem is caused by a lifetime issue: if you create a Widget in a Ruby variable, Ruby basically controls the lifetime of the widget. But the variable "wdg" goes out of scope, so the Ruby garbage collector is free to destroy the object when it wants to.
I think what happens now is that after leaving the function, the widget is shown because the Widget object is not destroyed yet. But after some time, the garbage collector will release the memory and your object will be lost causing the crash.
The easiest solution is to give the widget a parent, for example the main window:
When you do so, the ownership will be transferred to Qt and Ruby does not delete the Widget. As a general rule, every widget should have a parent, except very top level windows. For those you could use global variables to keep the objects. These are not cleaned up, because they don't go out of scope.
But if you use a parent for the widget, you should use "WA_DeleteOnClose" because your object will persist if you close the window causing a memory leak.
Matthias
Hi Matthias,
Thanks for your explanation. After I add a parent to the variable "wdg", the "wdg" window is embedded into klayout window and can't be moved or adjusted for window size. I want it floating. Please see below modified code for my class of "UI_Main". As I set 0x00000001 to the window flag of "wdg" as "wdg = QWidget.new(app, 0x00000001)", the "wdg" window can be floting for moving or adjusting. But when i keep resizing its window size by draging, same problem of klayout crash still happens. I think there must be something wrong in my logistic of coding. Hopefully i could know more from you. Thanks a lot.
covalent
Hi covalent,
I think the reason why you see it "embedded" within the main KLayout window is because
wdg
is aQWidget
, not aQDialog
orQMainWindow
. I have adapted the code to the latter, as follows, for my 0.24-python-eval version:Now that has the
wdg
as a child widget to aQMainWindow
instance, which in turn has KLayout's main window as its parent.Interestingly, this again exhibits the freeze as discussed earlier, at least for me under Win7.
Ok, I tried to completely follow Matthias' advice on properly "parenting" each and every one of the widgets in the code. I also removed the menu parts and
app.exec
to make it a simple macro to be run from the Macro Development window. Here's the complete code:The window (now a global constant and tied to the main KLayout window) still freezes (along with the KLayout main and Macro Develoment windows) when resized, under Windows 7.
Under Ubuntu (version r2739), simply starting this script crashes KLayout with the
You may have encountered a bug in the Ruby interpreter
... note.Hi all,
I think i found the cause of klayout crash problem. As i add "nil" action to the buttons, no matter how or how long i keep resizing the window size, there won't be klayout crash problem. So the button without corresponding action would make klayout crash. please refer to my code below. But the problem of memory accumulation while resizing the window size still exist.
covalent
This may or may not be a helpful comment. My apologies if it is not...
Did you know you can create complicated ui's using QT Creator, save it as a .ui file, and then call it in KLayout script? It's possible you weren't aware of that solution (but it's also possible that you want to code all this QT stuff inside KLayout for your own reasons).
Because then the Qt stuff is not owned by ruby and so ruby's garbage collection "can't touch this" -- I believe.
Anyway, that could solve the problem -- even if only in the short term. Or, it could be actually a better solution for you (less coding, but more mouse clicking..).
Here's an example.
Hi all,
I can reproduce the issue, although not that easily. Plus I can give an explanation:
The problem is basically the nesting of layouts. As mentioned earlier, it's not possible for Ruby to tell whether an object is owned by Qt without further knowledge. If the object has a parent, it will assume that Qt has the ownership. That works for the widgets, but not for the layouts. Except for the first layout, Qt refuses to use the widget as the parent (that's why you get messages like "trying to add a layout to a widget that already has one"). For the three following layouts there is no parent and Qt will assume ownership. Only later on, these layouts are added as sub-layouts, but at this point, Ruby has already taken over the ownership and will delete these layouts when the garbage collector cleans up memory. That will cause the crash.
Bottom line is, nested layouts don't work reliably when you create them explicitly. I'll try to fix this in later versions.
But David is right because using .ui files creates the layouts without interaction of Ruby and the program does not crash.
Another workaround is to not use nested layouts. You can use frames as sub-widgets.
Or you can use a single grid layout in your case:
Please also note that this code will avoid keeping "stale" window instances by deleting existing ones if one exists. I also added "WA_DeleteOnClose" to delete the object when the window is closed.
This version does no longer crash on my installation.
Matthias
I used your above code to insert widgets in grid layout. As you said, no klayout crash problem. Thanks for your cause identification.
But there is still another problem that the memory usage of klayout will keep accumulating as i opened the wdg window but did nothing. I did a test that as i opened the klayout and call the wdg window, the memory showed on my windows task manager is about 82000K. After 10 minutes, the memory usage became about 100000K. In this 10 minute period, i didn't do anything. Then when i close the wdg window, the memory wasn't released to orignal 82000K. Btw if you resize the window, the memory accumulation speed seems more obvious. Could i ask if you also have such problem or it is my own problem ?
Best regards,
covalent
Hi covalent,
I can see some memory allocation of roughly the same magnitude, but it seems to saturate in my case after allocating 20M of memory. I'll have to investigate that, I think it's the cost of some Ruby objects being allocated in background event handlers. To me it looks like the garbage collector is not quite effective then.
Do you observe saturation too? Does the memory still increase after you explicitly call the GC (run "GC.start") in the macro IDE's console)?
I shall try that on Python too - Python has a different memory management model based on reference counting and should show a different behaviour.
Matthias
Hi all,
here is my translation to Python:
Using this code, I still see increasing memory consumption on the Windows 7 0.24-python-eval version. But I found something else that might help to pinpoint the problem:
klayout
process constantly burns CPU cycles. Not too many (4% on my machine), but still more than I would expect from an application sitting idle.FriendFX
I did same test which friendfx did. The memory indeed keep inceasing while button got focus. When i click klayout main window to make the wdg window including the buttons lose focus, the memory stop increase. Regarding memory increase saturation, i didn't see it. i tested to make wdg window with "Activate" button with focus idle more than 30min, the klayout memory increase from 86M to 120M.
In addition to the problem of memory increase due to the "button focus" issue, to resize the window size also make memory usage increase quickly as observed by friendfx previously. i did a test that to keep dragging the window edge adjusting its window size, the memory usage increases to more than 200M, after release the mouse button, the memory still wasn't released.
covalent
Hi all,
thanks for performing these tests.
I see some memory increase but not as pronounced. I assume the problem is caused by some events being sent to the widgets continuously (timer, mouse move etc.). A Qt widget needs the ability to reimplement event handler methods and this will cause a little allocation of memory in the script's interpreter space.
I doubt that that's a real leak but apparently the memory is not properly made available again. I'll try to debug this. I would help to know whether calling GC.start will at least slow down the memory consumption. I my case (Ubuntu) it seems to do.
Matthias