can’t figure out how to make it work…
I have a progressbar in xaml:
<ProgressBar x:Name="pbar" Height="30" Margin="0,0,0,0" VerticalAlignment="Center" Width="500" HorizontalAlignment="Center"/>
and I have a class in my python script:
class CreateProgressWindow(Window):
def __init__(self):
wpf.LoadComponent(self, os.path.dirname(__file__) + '\window.xaml')
def update(self, value):
self.pbar.Value = value
if self.pbar.Value == self.pbar.Maximum:
self.Close()
I want to make the value jump inside a for loop:
progressform = CreateProgressWindow()
progressform.ShowDialog()
for i in range(100):
CreateProgressWindow.update(i)
does anyone know how to fix it? really can’t find any info on this…
Thanks!
Hi,
you have some issues with threads:
- ShowDialog() blocks the current thread
- A wpf control can only be modified by the thread that owns it.
import clr
import sys
import System
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\DLLs')
try:
clr.AddReference("IronPython.Wpf")
clr.AddReference('System.Core')
clr.AddReference('System.Xml')
clr.AddReference('PresentationCore')
clr.AddReference('PresentationFramework')
clr.AddReferenceByPartialName("WindowsBase")
except IOError:
raise
from System.IO import StringReader
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application
try:
import wpf
import time
except ImportError:
raise
class CreateProgressWindow(Window):
LAYOUT = '''
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowPgb5"
Height="300"
Width="300">
<Grid>
<ProgressBar
Grid.Column="0"
Grid.Row="0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="40,122,0,0"
Width="210"
Height="20"
x:Name="pbar" />
</Grid>
</Window>
'''
def __init__(self):
self.ui = wpf.LoadComponent(self, StringReader(CreateProgressWindow.LAYOUT))
def _dispatch_updater(self):
# ask WPF dispatcher for gui update
self.pbar.Dispatcher.Invoke(System.Action(self._update_pbar),
System.Windows.Threading.DispatcherPriority.Background)
def _update_pbar(self):
self.pbar.Value = self.new_value
if self.pbar.Value == self.pbar.Maximum:
self.Close()
def update_progress(self, value):
self.new_value = value
self._dispatch_updater()
pb = CreateProgressWindow()
pb.Show()
for i in range(1, 101):
time.sleep(0.05)
pb.update_progress(i)
you have a good example here
https://github.com/eirannejad/pyRevit/blob/528940e1a3593f1ae5bd9bfd964d2f37fb9d45e1/pyrevitlib/pyrevit/forms/__init__.py
10 Likes
You can also see the pyRevit example run if you install pyRevit and the developer tool extensions. Pretty cool.
1 Like
thank you so much! @c.poupin
really appreciate!
@c.poupin by the way can I use binding method in wpf to control progressbar value? like:
<ProgressBar x:Name="pbar" Value="{Binding new_value}" Height="30" Margin="0,0,0,0" VerticalAlignment="Center" Width="500" HorizontalAlignment="Center"/>
I don’t know, I guess it is necessary to use MVVM model and event
1 Like