I'm beginning with Rubymotion development, and I'm creating my first NSTableView with custom cells.
The following code is working, but I cannot manage to see how I should declare the NSTableCellView with Teacup layout (in order to move frame size in my stylesheet)
def tableView(table_view, viewForTableColumn: column, row: row_index)
cell_identifier = 'cell_id'
cell = table_view.makeViewWithIdentifier(cell_identifier, owner: self)
unless cell
cell = NSTableCellView.alloc.initWithFrame(CGRectMake(0, 0, table_view.bounds.size.width, rowHeight))
cell.identifier = cell_identifier
layout(cell) do
subview(NSTextField, :cell_text)
end
end
cell.subviews[0].stringValue = "value for #{row_index}"
cell
end
I already tried this code but it's not working:
def tableView(table_view, viewForTableColumn: column, row: row_index)
cell_identifier = 'cell_id'
#cell = table_view.makeViewWithIdentifier(cell_identifier, owner: self)
unless #cell
layout(nil, :root) do
#cell = subview(NSTableCellView, :cell_view) do |cell|
cell.identifier = cell_identifier
subview(NSTextField, :cell_text)
end
end
end
#cell.subviews[0].stringValue = "value for #{row_index}"
#cell
end
Thanks for your help
It should work if you assign the stylesheet and call reapply!
cell.stylesheet = :stylesheet
cell.reapply!
Related
The line: pics.box.signal_connect("button_press_event"){pics.nuImage}, triggers nuImage and adds 1 to the picindex counter upon clicking, making the current image destroy, and next image show. I would like to make this automatic, like a slideshow without having to click. It needs to show a new image every x amount of seconds, using a sleep or something like GLib.timeout_add_seconds (), but I do not understand how to implement these options to continue looping without any user input. Thank you for your help, I am very new to ruby.
require 'gtk2'
class Pics
attr_accessor :pile, :picindex, :imgLoaded, :image, :box, :window, :time
def initialize
#window = Gtk::Window.new()
#window.signal_connect("destroy"){Gtk.main_quit}
pic1 = "1.jpg"
pic2 = "2.jpg"
pic3 = "3.jpg"
pic4 = "4.jpg"
#pile = [pic1, pic2, pic3, pic4]
#picindex = 0
self.getImage
#box = Gtk::EventBox.new.add(#image)
#time = true
end
def nuImage
#box.remove(#image)
#picindex = #picindex + 1
#picindex = 0 if #picindex == #pile.length
self.getImage
#box.add(#image)
#box.show
end
def getImage
#imgLoaded = #pile[#picindex]
img = Gdk::Pixbuf.new(#imgLoaded, 556, 900)
#image = Gtk::Image.new(img)
#image.show
end
end # class Pics
pics = Pics.new
pics.box.signal_connect("button_press_event"){pics.nuImage}
pics.window.set_default_size(556, 900)
pics.window.add(pics.box)
pics.window.show_all
Gtk.main
the following code is an implementation:
GLib::Timeout.add(1000) do
pics.nuImage if pics.time
true
end
pics.window.signal_connect("key_press_event") do |_window, event|
case event.keyval
when Gdk::Keyval::GDK_KEY_space
pics.time = !pics.time
end
end
more details: http://ruby-gnome2.sourceforge.jp/hiki.cgi?GLib%3A%3ATimeout
related: Ruby GTK Pixbuf timed image change
I am creating an image slideshow in ruby, using gtk pixbuf to load images. I am very new to ruby & GTK, this may be an stupid question.
Currently image changes are linked to the GUI button_press_event, I would like them to change /refresh automatically based on a set time, like a slideshow or animation. I saw the gtk animation using a gif method, but I would like to use individual jpeg files inline sequence, so that I can set the time to show a slide. Once the loop has gone through all the images, the GUI should display buttons for replay or quit. ( I haven't used #time yet, it is just there for possibilities ) Thanks for any suggestions;
require 'gtk2'
class Pics
attr_accessor :pile, :picindex, :imgLoaded, :image, :box, :window, :time
def initialize
#window = Gtk::Window.new()
#window.signal_connect("destroy"){Gtk.main_quit}
pic1 = "1.jpg"
pic2 = "2.jpg"
pic3 = "3.jpg"
pic4 = "4.jpg"
#pile = [pic1, pic2, pic3, pic4]
#picindex = 0
self.getImage
#box = Gtk::EventBox.new.add(#image)
#time = true
end
def nuImage
#box.remove(#image)
#picindex = #picindex + 1
#picindex = 0 if #picindex == #pile.length
self.getImage
#box.add(#image)
#box.show
end
def getImage
#imgLoaded = #pile[#picindex]
img = Gdk::Pixbuf.new(#imgLoaded, 556, 900)
#image = Gtk::Image.new(img)
#image.show
end
end # class Pics
pics = Pics.new
pics.box.signal_connect("button_press_event"){pics.nuImage}
pics.window.set_default_size(556, 900)
pics.window.add(pics.box)
pics.window.show_all
Gtk.main
use GLib.timeout_add () or GLib.timeout_add_seconds (). Return False if you don't want to use it anymore.read GLib documentation, Section: Main Event Loop
This is a solution:
def start_button__clicked(but)
#thread = Thread.new {
loop do
next_button__clicked
sleep(2)
end
end
def stop_button__clicked(but)
#thread.kill
end
This is how I would do it in visual ruby. Its basically the same.
You'd just have a form with a button named "start_button" and "stop_button" etc.
the following code is an implementation:
GLib::Timeout.add(1000) do
pics.nuImage if pics.time
true
end
pics.window.signal_connect("key_press_event") do |_window, event|
case event.keyval
when Gdk::Keyval::GDK_KEY_space
pics.time = !pics.time
end
end
more details:
http://ruby-gnome2.sourceforge.jp/hiki.cgi?GLib%3A%3ATimeout
My only GUI experience is with java.swing. I'm using PySide to update which of two QGridLayouts are set to a QLabel depending on a button press, but the actual update isn't happening. Making a call to self.update() after lines 123 and 130 didn't work. Should I be using a repaint event or something?
def displaySimulator(self):
if self.sim_vis == True: pass
else:
self.sim_vis = True
self.graph_vis = False
self.options.setLayout(self.simulator_settings)
def displayGraphing(self):
if self.graph_vis == True: pass
else:
self.graph_vis = True
self.sim_vis = False
self.options.setLayout(self.graphing_settings)
Here's the full code.
----------------------------------------------------------------------------------
Also, the toolbar label at the top is way too big...
self.layout.setRowMinimumHeight(0,20)
self.layout.setColumnMinimumWidth(0,250)
self.layout.setColumnMinimumWidth(1,1000)
setColumnMinimumWidth() works fine but setRowMinimumHeight() doesn't seem to work at all. I'm still a little confused about how the size of QWidgets are affected by layouts, containers, and subwidgets...perhaps I need to adjust the size of the QLabel, toolbar?
Try using a QWidget instead of a QLabel for self.options. Does that change anything?
For the toolbar spacing, do addStretch() after you add the last widget to the layout, but note that if you use a layout in a toolbar, you lose the built-in capabilities for it to autosize and hide buttons in a "... more options ..." type thing.
Since you name your object a toolbar I would actually make it a QToolbar. I would like to point out some styling points, because you said you were new.
import * is always bad for many reasons. You should know what you are importing and from where.
from PySide import QtGui, QtCore
Since you have a main GUI that you are running I would make that a QMainWindow. I would then add a menu bar and move some of your functionality to a file menu or edit menu.
This is just my style and how I like to do things
import sys
from PySide import QtGui, QtCore
class SimulatorWindow(QtGui.QMainWindow):
"""Application for running a simulator and displaying the resutls."""
def __init__(self):
super(SimulatorWindow, self).__init__()
self.setWindowTitle("Simulator") # Main window
# Properties
self.main_menu = None
self.simulator = None
self.export_action = None
self.settings_action = None
self.exit_action = None
self.initUI()
self.initMenu()
self.resize(600, 400)
# end Constructor
# Builds Simulator GUI
def initUI(self):
self.simulator = Simulator()
self.setCentralWidget(self.simulator)
self.addToolBar(self.simulator.toolbar)
# end initUI
def initMenu(self):
"""Initialize the menu bar."""
menubar = self.menuBar()
# ===== File Menu =====
self.file_menu = menubar.addMenu('&File')
# Export action
iexport = QtGui.QIcon()
self.export_action = QtGui.QAction(iexport, "Export", self)
self.export_action.triggered.connect(self.export)
self.file_menu.addAction(self.export_action)
# Separator
self.file_menu.addSeparator()
# Simulator Settings Dialog action
isettings = QtGui.QIcon()
self.settings_action = QtGui.QAction(isettings, "Settings", self)
self.settings_action.triggered.connect(self.simulator.dialog.show)
self.file_menu.addAction(self.settings_action)
# Exit action
iexit = QtGui.QIcon('exit.png')
self.exit_action = QtGui.QAction(iexit, '&Exit', self)
self.exit_action.triggered.connect(self.close)
self.file_menu.addAction(self.exit_action)
# ===== Edit Menu =====
self.edit_menu = menubar.addMenu('&Edit')
self.edit_menu.addAction(self.simulator.run_action)
# end initMenu
def export(self):
"""Export the simulation file."""
pass
# end export
# end class SimulatorWindow
class Simulator(QtGui.QWidget):
"""Simulator display."""
def __init__(self):
super().__init__()
#Properties
self.toolbar = None
self.dialog = None
self.run_action = None
# Layout
self.main_layout = QtGui.QGridLayout()
self.setLayout(self.main_layout)
# Graph
stuff = QtGui.QLabel("<font color=red size=300>Graphing stuff</font>")
stuff.setStyleSheet("QLabel {background-color: rgb(50,50,50); font-size:250;}")
stuff.setAlignment(QtCore.Qt.AlignCenter)
graph = QtGui.QLabel("<font color=green size=250>Graph here</font>")
graph.setStyleSheet("QLabel {background-color: rgb(0,0,0); font-size:250;}")
graph.setAlignment(QtCore.Qt.AlignCenter)
graph.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
self.main_layout.addWidget(stuff)
self.main_layout.addWidget(graph)
self.initToolbar()
self.initSettingsDialog()
# end Constructor
def initToolbar(self):
self.toolbar = QtGui.QToolBar()
irun = QtGui.QIcon()
self.run_action = QtGui.QAction(irun, "Run", self)
self.run_action.triggered.connect(self.run)
self.toolbar.addAction(self.run_action)
# end initToolbar
def initSettingsDialog(self):
"""Initialize the Settings dialog."""
self.dialog = QtGui.QDialog(self)
self.dialog.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowSystemMenuHint)
layout = QtGui.QGridLayout()
self.dialog.setLayout(layout)
# Initialize the Widgets
title = QtGui.QLabel("<font size=6>Simulator Settings</font>")
num_sim = QtGui.QLineEdit("Number of simulations")
num_trials = QtGui.QLineEdit("Number of trials (per learning phase)")
network = QtGui.QComboBox()
subject = QtGui.QComboBox()
# Set the layout
layout.addWidget(title, 0, 0, 1, 2, QtCore.Qt.AlignCenter)
layout.addWidget(num_sim, 1, 0)
layout.addWidget(num_trials, 1, 1)
layout.addWidget(network, 2, 0)
layout.addWidget(subject, 2, 1)
# end initSettingsDialog
def run(self):
"""Run the simulation."""
pass
# end run
# end class Simulator
def main():
"""Run the application."""
app = QtGui.QApplication(sys.argv)
window = SimulatorWindow()
window.show()
return app.exec_()
# end main
if __name__ == "__main__":
sys.exit(main())
Edit: this first part has been solved
Sorry for the probably noob question, but I've searched for two days without finding an answer.
I've read the Objective-C documentation on event handling but I'm really not able to translate that to Rubymotion.
I am simply trying to define a mouseDown event on an NSView that contains a subview with an image.
Any hint?
Thanks.
New issue
EXAMPLE CODE: updated with new issue (look at the comments)
class ViewController < NSView
def loadWindow
#window = NSWindow.alloc.initWithContentRect([[400, 500], [480, 200]],
styleMask: NSTitledWindowMask|NSClosableWindowMask,
backing: NSBackingStoreBuffered,
defer: false)
#window.setTitle("Test")
#cView = ViewController.alloc.initWithFrame([[400,500], [480, 200]])
#window.setContentView(#cView)
#iView = NSImageView.alloc.initWithFrame([[100,100], [30, 30]])
#iView.setImage(NSImage.imageNamed "Icon")
#cView.addSubview(#iView)
#window.orderFrontRegardless
#window.makeKeyWindow
#var = "variable"
puts #var # This works and puts "variable"
end
def mouseDown(event)
puts "mouse click" # This puts "mouse click"
puts #var # This puts a blank line
end
end
Your answer was in the docs, but you just missed it :)
Handling a mouse down event is handled by NSView's parent class NSResponder:
https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSResponder_Class/Reference/Reference.html#//apple_ref/occ/instm/NSResponder/mouseDown:
You just need to define mouseDown on your view.
class MyView < NSView
def mouseDown(event)
# what you want to do
end
end
if use the sugarcube gem, you can achieve it like this:
button = UIButton.alloc.initWithFrame([0, 0, 10, 10])
button.on(:touch) { my_code }
button.on(:touch_up_outside, :touch_cancel) { |event|
puts event.inspect
# my_code...
}
# remove handlers
button.off(:touch, :touch_up_outside, :touch_cancel)
button.off(:all)
detail: https://github.com/rubymotion/sugarcube
I need to show some treeview item text striked out text into a QT treeview from Ruby.
After some reading on QT documentation and much coding, I found that only when rendering font in bold, also the strikeout was rendered.
So I wonder, where I'm doing wrong?
This is the code to achive the result shown above. Note as I set strikeout for every even row item.
I'm using Ruby 1.8.7 and Qt 4.6.2 and qt4ruby 4.4.3-6 on Mandriva Linux.
require 'Qt4'
require 'date'
class MyStandardItem < Qt::StandardItem
def initialize(str = nil)
super str
end
def data(role = Qt::UserRole + 1)
return super(role) unless role == Qt::FontRole
ret_val = Qt::Font.new()
#parameters for "fromString":font family, pointSizeF, pixelSize, QFont::StyleHint, QFont::Weight, QFont::Style, underline, strikeOut, fixedPitch, rawMode
ret_val.fromString "sans serif,-1,-1,0,0,0,0,0,0,0"
case role
when Qt::FontRole
ret_val.setStrikeOut(true) if (index.row % 2) == 0
if index.column == 1
ret_val.weight = Qt::Font.Bold
else
ret_val.weight = Qt::Font.Normal
end
return Qt::Variant.fromValue(ret_val)
end
return ret_val
end
end
Qt::Application.new(ARGV) do
treeview = Qt::TreeView.new do
model = Qt::StandardItemModel.new self
head = [MyStandardItem.new "Qt v. #{Qt.version}"]
head << MyStandardItem.new("Ruby v. #{VERSION}")
head << MyStandardItem.new("Qt4Ruby v. 4.4.3-6 (Mandriva)")
model.append_row head
(1..10).each do |i|
col0 = MyStandardItem.new 'some text'
col0.check_state = ((i % 3) == 0)? Qt.Checked : Qt.Unchecked
col0.checkable = true
col0.editable= false
col1 = MyStandardItem.new "line ##{i}"
col2 = MyStandardItem.new((Date.today + i).strftime '%d/%m/%y')
model.append_row [col0, col1, col2]
end
self.model = model
show
end
exec
end
Eventually I find an hackish trick to overcome this problem. Playing around after reading again the enum QFont::Weight description I tried to set
ret_val.weight = 51 # Qt::Font.Normal value is 50
instead of
ret_val.weight = Qt::Font.Normal
and magically the normal text appears striked out!
Maybe this strange behaviour is due to a bug on QT?