QtRangeSlider's QLabeledDoubleRangeSlider Not Working With Negative Values - pyqt5

Objective: To have a slider that:
Has (2) slider handles
Can accept int and float values when defining the slider domain
Can step in non-integer increments
Can be defined over a domain having negative values
Attempt: The code I've tried is below. Further, I was able to find a package qtrangeslider, pip install qtrangeslider. The package nearly covers all of my objectives.
Problem: The package qtrangeslider falls short when handling domains having negative values. The package is unable to accurately catch mouse clicks on the slider handles when dealing with a domain covering negative values.
Question: Would any one be skilled enough to track down why the package is failing and/or suggest a different package that meets my stated objectives.
'''
''' Begin : Import source dependencies '''
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
from qtrangeslider import QLabeledDoubleRangeSlider
''' End : Import source dependencies '''
''' Begin : Class definition of double handle slider '''
class AppDoubleRangeSlider( QtWidgets.QWidget ):
# Set the default style sheet definition
defaultStyleSpec = """
QSlider {
min-height: 10px;
}
QSlider::groove:horizontal {
border: 3px;
background: qradialgradient(cx:0, cy:0, radius: 1.2, fx:0.5, fy:0.5, stop:0 #B0C4DE, stop:1 #808080);
height: 20px;
margin: 15px 0;
border-radius: 10px;
}
QSlider::handle {
background: qradialgradient(cx:0, cy:0, radius: 1.2, fx:0.5, fy:0.5, stop:0 #00BFFF, stop:1 #1E90FF);
height: 20px;
width: 20px;
border-radius: 10px;
}
/*
"QSlider::sub-page" is the one exception ...
(it styles the area to the left of the QSlider handle)
*/
QSlider::sub-page:horizontal {
background: #32CD32;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}
/*
for QRangeSlider: use "qproperty-barColor". "sub-page" will not work.
*/
QSlider {
qproperty-barColor: #32CD32;
}
"""
''' Begin : Class constructor '''
def __init__(self, parent=None, minSliderVal=0.0, maxSliderVal=1.0, handleLeftValue=0.0, handleRightValue=1.0):
# Call the parent constructor
super( AppDoubleRangeSlider, self ).__init__( parent )
# Track the inputs
self.minSliderVal = minSliderVal
self.maxSliderVal = maxSliderVal
self.handleLeftValue = handleLeftValue
self.handleRightValue = handleRightValue
# Initialize class member defaults
self.initClassDefaults()
# Set window properties
self.initWindowProperties()
# Initialize the application layout space
self.initLayoutSpace()
# Initialize the widgets
self.initWidgets()
# Finalize layout settings
self.finalizeLayout()
''' End : Constructor '''
''' Begin : Method to set window properties '''
def initClassDefaults(self):
# Initialize a double handed slider with input parameters
self.appSlider = QLabeledDoubleRangeSlider( QtCore.Qt.Horizontal )
self.appSlider.setStyleSheet( self.defaultStyleSpec )
self.appSlider.setRange( self.minSliderVal, self.maxSliderVal )
self.appSlider.setMinimum( self.minSliderVal )
self.appSlider.setMaximum( self.maxSliderVal )
self.appSlider.setValue( (self.handleLeftValue, self.handleRightValue) )
# Connect the slider to a callback to handle value changes
self.appSlider.valueChanged.connect( self.callbackValueChange )
''' End : Method to set window properties '''
''' Begin : Method to return slider handle values '''
def getSliderValues(self):
print((self.handleLeftValue, self.handleRightValue),'\n\n')
# Return the slider's handle values
return (self.handleLeftValue, self.handleRightValue)
''' End : Method to return slider handle values '''
''' Begin : Method to respond to value changes '''
def callbackValueChange(self, value):
print((self.handleLeftValue, self.handleRightValue),'\n\n')
# Track the slider's handle values
self.handleLeftValue = value[ 0 ]
self.handleRightValue = value[ 1 ]
''' End : Method to respond to value changes '''
''' Begin : Method to set window properties '''
def initWindowProperties(self):
# Define the minimum app size
self.minAppWidth = 300
self.minAppHeight = 100
# Set minimum size constraints on the window
self.setMinimumWidth( self.minAppWidth )
self.setMinimumHeight( self.minAppHeight )
# Set initial window size
self.resize( self.minAppWidth, self.minAppHeight )
''' End : Method to set window properties '''
''' Begin : Method to initialize the application layout space '''
def initLayoutSpace(self):
# Initialize a layout
self.layoutRoot = QtWidgets.QHBoxLayout()
''' End : Method to initialize the application layout space '''
''' Begin : Method to initialize the application layout space '''
def initWidgets(self):
pass
''' End : Method to initialize the application layout space '''
''' Begin : Method to finalize layout settings '''
def finalizeLayout(self):
# Push the slider to the layout
self.layoutRoot.addWidget( self.appSlider )
# Finalize window layout
self.setLayout( self.layoutRoot )
''' End : Method to finalize layout settings '''
''' End : Class definition of double handle slider '''
from qtrangeslider import QDoubleRangeSlider
from PyQt5 import QtCore, QtGui, QtWidgets
app = QApplication( [ ] )
myApp = AppDoubleRangeSlider( minSliderVal=-1, maxSliderVal=1, handleLeftValue=-0.5, handleRightValue=0.5 )
myApp.show()
app.exec_()
'''

Related

How do I delay the execution of a function within tkinter button command

I am trying to simulate a computer player "clicking" a button after a human user clicks a button In a grid of buttons. If I use the .after method the 'state' of the button change is delayed but it executes my check_state() method which doesn't detect the change. When I try time.sleep() method it prolongs the human click but still immediately invokes the 'auto' click regardless of where I put it in my code. I want a delay between the human click and 'auto' click.
I have tried widget.after(1000) which gives the desired delay of 'auto' click, but doesn't allow my the change to be seen by my check_state() function. I have tried time.sleep() which delays the execution of the human button click but the 'auto' click is still immediately invokes regardless of which order I place the sleep() function in relation to the call to auto_click(). I know there are better practices for this code implementation like using class based structure which I plan on using once my logic and functionality issues are resolved. My code is as follows:
import tkinter as tk
import random
def app():
def auto_click():
grid_state = get_grid_state()
possible_clicks = []
for i in range(0, len(grid_state)):
if grid_state[i] == " ":
possible_clicks.append(i)
#debug.config(text=possible_moves)
click = random.choice(possible_clicks)
buttons[click].after(1000, lambda: buttons[click].config(text = "auto", state=tk.DISABLED))
#time.sleep(1)
check_grid_state()
check_grid_full()
debug.config(text="test")
def onclick(*arg):
global is_full
buttons[arg[0]].config(text = "clicked", state=tk.DISABLED)
check_grid_state()
check_grid_full()
if not is_full:
auto_click()
def check_grid_full():
global is_full
result=[]
for i in range(len(buttons)):
result.append(buttons[i].cget('state'))
r = [*set(result)]
if r == ['disabled']:
is_full = True
grid_status.config(text=is_full)
else:
is_full = False
Retrieve the current state of the grid
def get_grid_state():
grid_state =[]
for i in range(len(buttons)):
grid_state.append(buttons[i].cget('text'))
return grid_state
Check grid state
def check_grid_state():
grid_states.config(text=get_grid_state())
Global Variables
is_full = False
buttons = []
c=0
Window
root = tk.Tk()
root.title("Title")
Heading
label = tk.Label(root, text="grid state", font = ("Ariel black",22, "bold"))
label.pack()
Grid Frame
frame = tk.Frame(root)
frame.pack()
for row in range(3):
for column in range(3):
buttons.append(tk.Button(frame, text=f" ", font=("arial", "22"), state=tk.ACTIVE, height=2, width=2, command=lambda c=c: onclick(c)))
buttons[c].grid(row=row, column=column)
c += 1
Status bar
grid_states = tk.Label(root, text=f"")
grid_states.pack()
grid_status = tk.Label(root, text=f"")
grid_status.pack()
#btn_is = tk.Label(root, text=f"")
#btn_is.pack()
Debugging output label
debug = tk.Label(root, text="debug")
debug.pack()
Event loop
root.mainloop()
if name == "main":
app()

QUploader component in Julia

I have been developing an application in Julia using Genie Framework and Stipple, and the main task of this app is to implement Sobel and Prewitt operator. The problem that I am struggling with is the uploader component. So basically I am able to upload an image, on button click the image is transformed, but then when i upload another image and try to output the transformed version of it, the output that i get is still the old image. I have been trying to find the issue and I noticed that QUploader API has some methods that could help solve this problem: reset() method, or removeUploadedFiles() method, but I do not know how to call/use these functions regarding Julia syntax. Are there any solutions available?
const FILE_PATH = "public/sample.jpg"
const FINAL_PATH = "final.jpg"
#const IMGPATH = "demo.png"
model = Model |> init
on(model.process_s3) do _
model.imageurl[] = ""
#info "Working"
img = FileIO.load(FILE_PATH)
img_gray = Gray.(img)
#info img_gray
sobel_image = convert(Array{Float64}, img_gray)
lastImage = clamp01nan.(sobel(sobel_image, sobel3_kernel_x, sobel3_kernel_y))
save(joinpath(#__DIR__, "public", FINAL_PATH), lastImage)
model.imageurl[] = "/$FINAL_PATH#$(Base.time())" * string(rand())
#info model.imageurl[]
if (model.process_s3[])
model.process_s3[] = false
end
end
function ui(model)
[
page( model,
class = "container",
title = "Card Demo",
partial = true,
[
row( # row takes a tuple of cells. Creates a `div` HTML element with a CSS class named `row`.
cell([h1("Edge Detection Project")]),
)
row(
[
cell(class="st-module", [
h2("Initial Image"),
card(
class = "q-pa-md row items-start q-gutter-md",
uploader(
label = "Upload Image",
method = "POST",
:multiple,
url = "http://localhost:8000/upload",
field__name = "img",
:finish="finished",
ref="uploader"
),
),
btn("Sobel 3x3",color="primary", #click("process_s3 = true")),
])
cell(class="st-module", [
h2("Transformed Image"),
card(
class = "q-pa-md row items-start q-gutter-md",
#quasar(:img, src=:imageurl, spinner__color="white", style="height: 300px; max-width: 350px")
imageview(src=:imageurl, spinner__color="white", style="height: 250px; max-width: 250px")
),
])
],
)
],
),
]
end
route("/") do
html(ui(model), context = #__MODULE__)
end
route("/upload", method = POST) do
if infilespayload(:img)
#info Requests.filename(filespayload(:img))
open(FILE_PATH, "w") do io
write(FILE_PATH, filespayload(:img).data)
#info File
end
else
#info "No image uploaded"
end
Genie.Renderer.redirect(:get)
end
# isrunning(:webserver) || up()
Replace:
"/$FINAL_PATH#$(Base.time())"
with
"/$(FINAL_PATH)?t=$(Base.time())"
Explanation:
# makes just an anchor link to an HTML document. This will obviously result in buffering the document as the browser might just look for different anchors (and not find them) yet has no motivation to re-download.
On the other hand adding the ? makes the request actually different every time (understood by browser as a different document). In result the cache will not be used - a new copy gets requested.

Dynamically changing trait

Is it possible to have two classes
class SimulationDigitizer(HasTraits):
width = Int(1920)
height = Int(1080)
name = 'Simulation'
class FileDigitizer(HasTraits):
Filename = File
name = 'File'
and another class 'Digitizer' having an attribute (or trait) UserDigitizer whose edition dialog will propose a drop-down list with 'Simulation' and 'File' and, depending on the choice, the instance edition of either FileDigitizer or SimulationDigitizer and get the result in UserDigitizer ?
Thanks
Thanks Jonathan, you are right, the problem is to select the appropriate subcomponent among many possible.
I ended with the following code, I guess it can be improved in many ways. I am new both to Python and Traits.
# -*- coding: utf-8 -*-
from traits.api import HasTraits, Int, File, Enum, Instance
from traitsui.api import View, Item, Handler, HGroup, InstanceEditor
class UserComponent ( HasTraits ):
""" An empty class from which all user component classes are
derived.
"""
pass
class SimulationDigitizer(UserComponent):
width = Int(1920)
height = Int(1080)
nature = 'Simulation'
class FileDigitizer(UserComponent):
filename = File
nature = 'Reading a file'
UserDigitizers = [FileDigitizer, SimulationDigitizer]
class UserComponentHandler(Handler):
def __init__(self,_user_components_dict):
Handler.__init__(self)
self._user_components_dict = _user_components_dict
def object_user_component_nature_changed ( self, info ):
# Find new UserComponent class from string in user_component_nature
new_user_component = self._user_components_dict[info.object.user_component_nature]
# If different, change user_component value
if info.object.user_component is not new_user_component:
info.object.user_component = new_user_component
class Digitizer(HasTraits):
user_component_nature = Enum([x().nature for x in UserDigitizers])
_user_file_digitizer = FileDigitizer()
_user_simulation_digitizer = SimulationDigitizer()
# Dictionary with keys = nature and values = user digitizers
_user_digitizers_dict = {x.nature: x for x in [_user_file_digitizer,_user_simulation_digitizer]}
user_component = Enum(_user_file_digitizer,_user_simulation_digitizer)
view = View(HGroup(Item('user_component_nature',
label = 'Nature'),
Item('user_component',
show_label = False,
editor = InstanceEditor(label = 'Edit',
kind = 'modal'))),
handler = UserComponentHandler(_user_digitizers_dict))
d = Digitizer()
if __name__ == '__main__':
d.configure_traits()

Python 3.x tkinter - can't get checkbox' variable value

Please help! As it says in the title - I can't get checkbox' variable value.
def init_widgets(self):
ttk.Button(self.root, command=self.insert_txt, text='Button', width='10').place(x=10, y=10)
...
cbcc = ttk.Checkbutton(root, text="Damage", onvalue="on", offvalue='off').place(x=235, y=12)
...
def insert_txt(self):
...
cbcd = StringVar()
cbcd.get()
print(cbcd)
if cbcd == "on":
self.damage
else:
Print delivers "PY_VAR2" and counting up from there with every time I click (PY_VAR3, etc.)
It seems in your code, the argument 'variable' in your Checkbutton is not bounded, furthermore to get the value from IntVar or StringVar you would use (IntVar.get(), StringVar().get()), you could use the next code as example to use Checkbutton widget.
'''
CheckBox Test
References:
http://effbot.org/tkinterbook/checkbutton.htm
'''
from tkinter import *
class App:
def __init__(self, master):
self.var = IntVar() #This is the variable bounded to checkbutton to
#get the checkbutton state value
#
frame = Frame(master)
frame.pack()
self.checkbutton = Checkbutton(frame, text="Hello Checkbutton",
command=self.say_hello, variable=self.var)
self.checkbutton.pack(side=LEFT)
#
self.button = Button(frame, text="QUIT", fg="red", command=frame.quit)
self.button.pack(side=LEFT)
def say_hello(self):
'''
Function Bounded to Checkbutton in command parameter, every click
either check or un-check print the current state of the checkbutton
'''
print("State Changed:", self.var.get())
if __name__ == '__main__':
root = Tk()
app = App(root)
#
root.mainloop()
root.destroy() # Quit the App when you click "Quit"
Every click on the check button, you will see printed in the console the value of the current state for the checkbutton. You can check the next reference to get an general overview tkinter widgets: http://effbot.org/tkinterbook/checkbutton.htm
I hope this snippet helps you.
Very Best Regards.

Override window close behavior

I want to catch all tries to close some specific existing Cocoa window and add some own handler (which might indeed really close it or do something different).
I had different solutions in mind to do this. One was:
I want to replace the window close button of an existing Cocoa window at runtime with an own close widget where I can add some own code.
Right now, I have this code:
import objc
_NSThemeCloseWidget = objc.lookUpClass("_NSThemeCloseWidget")
def find_close_widget(window):
contentView = window.contentView()
grayFrame = contentView.superview()
for i in range(len(grayFrame.subviews())):
v = grayFrame.subviews()[i]
if isinstance(v, _NSThemeCloseWidget):
return v, i, grayFrame
class CustomCloseWidget(_NSThemeCloseWidget):
pass
def replace_close_widget(window, clazz=CustomCloseWidget):
v, i, grayFrame = find_close_widget(window)
newv = clazz.alloc().init()
grayFrame.subviews()[i] = newv
However, this doesn't seem quite right. (It crashes.)
The close widget isn't the only way to close the window. There's a public API to obtain the widget, so you don't need to go rifling through the frame view's subviews, but that's the wrong path anyway.
The right way is to make an object to be the window's delegate, and interfere with the window's closure there. Ideally, you should set the window's delegate in between creating the window and ordering it in.
I am going another route now. This is partly Chrome related but it can easily be adopted elsewhere. I wanted to catch several actions for closing the window as early as possible to avoid any other cleanups or so which resulted in the window being in a strange state.
def check_close_callback(obj):
# check ...
return True # or:
return False
import objc
BrowserWindowController = objc.lookUpClass("BrowserWindowController")
# copied from objc.signature to avoid warning
def my_signature(signature, **kw):
from objc._objc import selector
kw['signature'] = signature
def makeSignature(func):
return selector(func, **kw)
return makeSignature
windowWillCloseSig = "c12#0:4#8" # BrowserWindowController.windowWillClose_.signature
commandDispatchSig = "v12#0:4#8"
class BrowserWindowController(objc.Category(BrowserWindowController)):
#my_signature(windowWillCloseSig)
def myWindowShouldClose_(self, sender):
print "myWindowShouldClose", self, sender
if not check_close_callback(self): return objc.NO
return self.myWindowShouldClose_(sender) # this is no recursion when we exchanged the methods
#my_signature(commandDispatchSig)
def myCommandDispatch_(self, cmd):
try: print "myCommandDispatch_", self, cmd
except: pass # like <type 'exceptions.UnicodeEncodeError'>: 'ascii' codec can't encode character u'\u2026' in position 37: ordinal not in range(128)
if cmd.tag() == 34015: # IDC_CLOSE_TAB
if not check_close_callback(self): return
self.myCommandDispatch_(cmd)
from ctypes import *
capi = pythonapi
# id objc_getClass(const char *name)
capi.objc_getClass.restype = c_void_p
capi.objc_getClass.argtypes = [c_char_p]
# SEL sel_registerName(const char *str)
capi.sel_registerName.restype = c_void_p
capi.sel_registerName.argtypes = [c_char_p]
def capi_get_selector(name):
return c_void_p(capi.sel_registerName(name))
# Method class_getInstanceMethod(Class aClass, SEL aSelector)
# Will also search superclass for implementations.
capi.class_getInstanceMethod.restype = c_void_p
capi.class_getInstanceMethod.argtypes = [c_void_p, c_void_p]
# void method_exchangeImplementations(Method m1, Method m2)
capi.method_exchangeImplementations.restype = None
capi.method_exchangeImplementations.argtypes = [c_void_p, c_void_p]
def method_exchange(className, origSelName, newSelName):
clazz = capi.objc_getClass(className)
origMethod = capi.class_getInstanceMethod(clazz, capi_get_selector(origSelName))
newMethod = capi.class_getInstanceMethod(clazz, capi_get_selector(newSelName))
capi.method_exchangeImplementations(origMethod, newMethod)
def hook_into_windowShouldClose():
method_exchange("BrowserWindowController", "windowShouldClose:", "myWindowShouldClose:")
def hook_into_commandDispatch():
method_exchange("BrowserWindowController", "commandDispatch:", "myCommandDispatch:")
This code is from here and here.