Coder Social home page Coder Social logo

thisal-d / tkchart Goto Github PK

View Code? Open in Web Editor NEW
29.0 1.0 1.0 1.38 MB

tkchart is a Python library for creating live updating line charts in Tkinter.

Home Page: https://pypi.org/project/tkchart/

License: MIT License

Python 100.00%
linechart tkinter tkchart python-chart line-chart-for-python-tkinter ctk ctk-components customtkinter customtkinter-widgets customtkinterassets

tkchart's Issues

'width' and 'height' arguments must be passed to the constructor of the widget, not the place method

This doesnt seem to be working, i get the following error.

chart_1 = tkchart.LineChart(master=root

File "C:\ProgramData\Anaconda3\lib\site-packages\tkchart\LineChart.py", line 64, in init
self.configure_chart_geomatry()
File "C:\ProgramData\Anaconda3\lib\site-packages\tkchart\LineChart.py", line 74, in configure_chart_geomatry
self.chart_values_backgroud.place(width=self.left_space, y=self.top_space + self.y_space + self.horizontal_bar_size,
File "C:\ProgramData\Anaconda3\lib\site-packages\customtkinter\windows\widgets\core_widget_classes\ctk_base_class.py", line 272, in place
raise ValueError("'width' and 'height' arguments must be passed to the constructor of the widget, not the place method")
ValueError: 'width' and 'height' arguments must be passed to the constructor of the widget, not the place method

Some obstacles to use

The cget() function was not found, how should I go about getting the relevant parameter values? Also, the x-axis coordinate display function doesn't seem to be available?


没有发现cget()函数,我应该怎样去获取相关的参数值?此外,x轴坐标显示功能似乎也没有?

Line doesn't cross correctly with the grid sections.

Describe the bug
I am currently making a test program during my internship. I have come across a bug relating toward the y_axis_precision value. If I put the value to 0 to make it look cleaner I can see the line doesn't cross with the grid. If I put the value on 5 it will work correctly. Although I don't like the 5 decimals.

To Reproduce

import customtkinter as ctk
import tkchart
import ctypes
import main


class App(ctk.CTk):
    def __init__(self, main_app):
        super().__init__()
        self.main_app = main_app
        self.iconbitmap(r"C:\Users\rijken.b\Downloads\skalar_analytical_bv_logo_Zoy_icon.ico")
        self.resizable(width=False, height=False)
        self.title("Chart System")
        self.Menu_One_Show = True
        self.Menu_Two_Show = True
        self.Menu_Three_Show = True
        self.Menu_Two_Slider = True
        self.Place_Button_Y = 28
        self.Place_Button_X = 140
        self.sliderchannel_One = None
        self.sliderchannel_Two = None
        self.sliderchannel_Three = None
        self.inputchannel_One = None
        self.inputchannel_Two = None
        self.inputchannel_Three = None
        self.error_message_slider_entry = None
        self.data_channel = 250
        self.format_value_one = 50
        self.format_value_two = 50
        self.format_value_three = 50
        self.status = True
        self.loading()

    def loading(self):
        self.Topbar()
        self.load_text()
        self.Masterchart()
        self.Chartline()
        self.Togglebutton()
        self.loop()

    def Topbar(self):
        self.Menu_One = ctk.CTkButton(self, text="Exit",command=self.Topbar_Menu_One)
        self.Menu_One.grid(row=0,column=0, sticky="W")
        self.Menu_Two = ctk.CTkButton(self, text="Settings", command=self.Topbar_Menu_Two)
        self.Menu_Two.grid(row=0,column=0, padx=140, sticky="W")

    def Topbar_Menu_One(self):
        if self.Menu_One_Show:
            self.Menu_Restart = ctk.CTkButton(self, text="Restart", command=self.restart)
            self.Menu_Restart.place(x=0, y=self.Place_Button_Y)
            self.Menu_Quit = ctk.CTkButton(self, text="Quit", command=self.destroy)
            self.Menu_Quit.place(x=0, y=self.Place_Button_Y*2)
        else:
            self.Menu_Restart.place_forget()
            self.Menu_Quit.place_forget()
        self.Menu_One_Show = not self.Menu_One_Show

    def Topbar_Menu_Two(self):
        if self.Menu_Two_Show:
            self.Menu_Sliders = ctk.CTkButton(self, text="Sliders", command=self.Topbar_Sliders)
            self.Menu_Sliders.place(x=self.Place_Button_X, y=self.Place_Button_Y)
        else:
            self.Menu_Sliders.place_forget()

        self.Menu_Two_Show = not self.Menu_Two_Show

    def Topbar_Sliders(self):
        if self.Menu_Two_Slider:
            self.Sliders()
        else:
            self.sliderchannel_One.grid_forget()
            self.sliderchannel_Two.grid_forget()
            self.sliderchannel_Three.grid_forget()
            self.inputchannel_One.grid_forget()
            self.inputchannel_Two.grid_forget()
            self.inputchannel_Three.grid_forget()
            if self.error_message_slider_entry:
                self.error_message_slider_entry.grid_forget()
        self.Menu_Two_Slider = not self.Menu_Two_Slider

    def load_text(self):
        self.StartupLabel = ctk.CTkLabel(text="Test system", master=self, font=ctk.CTkFont(size=15, weight="bold"),
                                         justify="center")
        self.StartupLabel.grid(row=1, column=0, padx=50, pady=10)

    def Masterchart(self):
        self.Masterchart = tkchart.LineChart(master=self,
                                             width=800,
                                             height=400,
                                             axis_size=5,

                                             y_axis_section_count=10,
                                             x_axis_section_count=20,
                                             y_axis_label_count=10,
                                             x_axis_label_count=10,

                                             y_axis_data="Sensor meting",
                                             x_axis_data="Seconden",
                                             x_axis_values=[1,2,3,4,5,6,7,8,9,10],
                                             y_axis_max_value=250,
                                             y_axis_precision=5,
                                             section_color="#404040",
                                             x_axis_font_color="#707070",
                                             y_axis_font_color="#707070",
                                             x_axis_data_font_color="lightblue",
                                             y_axis_data_font_color="lightblue",
                                             bg_color="#202020",
                                             fg_color="#202020",
                                             axis_color="#707070",

                                             data_font_style=("Arial", 15, "bold"),
                                             axis_font_style=("Arial", 10, "bold"),
                                             x_space=40,
                                             y_space=20,
                                             x_axis_data_position="side",
                                             y_axis_data_position="size"
                                             )
        self.Masterchart.grid(row=2, column=0, rowspan=3, padx=50, pady=50)

    def Chartline(self):
        self.Drawline_1 = tkchart.Line(master=self.Masterchart,
                                       color="lightblue",
                                       size=2)
        self.Drawline_2 = tkchart.Line(master=self.Masterchart,
                                       color="red",
                                       size=2)
        self.Drawline_3 = tkchart.Line(master=self.Masterchart,
                                       color="green",
                                       size=2)
    def Togglebutton(self):
        self.pausebutton = ctk.CTkButton(self, text="Stop/Start", command=self.toggle_status)
        self.pausebutton.grid(row=5, column=0, padx=30, pady=10)

    def Sliders(self):
        self.inputchannel_One = ctk.CTkEntry(self)
        self.inputchannel_One.grid(row=2, column=5, sticky="S")
        self.inputchannel_One.bind("<Return>", lambda event: self.set_slider_value(1))
        self.sliderchannel_One = ctk.CTkSlider(master=self, width=10, height=200, from_=0, to=100,
                                               progress_color="blue", orientation="vertical")
        self.sliderchannel_One.grid(row=4, column=5)

        self.inputchannel_Two = ctk.CTkEntry(self)
        self.inputchannel_Two.grid(row=2, column=6, sticky="S")
        self.inputchannel_Two.bind("<Return>", lambda event: self.set_slider_value(2))
        self.sliderchannel_Two = ctk.CTkSlider(master=self, width=10, height=200, from_=0, to=100,
                                               progress_color="blue", orientation="vertical")
        self.sliderchannel_Two.grid(row=4, column=6)

        self.inputchannel_Three = ctk.CTkEntry(self)
        self.inputchannel_Three.grid(row=2, column=7, sticky="S")
        self.inputchannel_Three.bind("<Return>", lambda event: self.set_slider_value(3))
        self.sliderchannel_Three = ctk.CTkSlider(master=self, width=10, height=200, from_=0, to=100,
                                               progress_color="blue", orientation="vertical")
        self.sliderchannel_Three.grid(row=4, column=7)

        self.update_entry_from_slider()
        self.bind("<Motion>", self.update_entry_from_slider)

    def set_slider_value(self, column):
        if column == 1:
            try:
                value_one = int(self.inputchannel_One.get())
                self.sliderchannel_One.set(value_one)
                self.update_entry_from_slider()
                self.error_message_slider_entry.configure(text="")
            except ValueError:
                self.error_slider_value(1)

        elif column == 2:
            try:
                value_two = int(self.inputchannel_Two.get())
                self.sliderchannel_Two.set(value_two)
                self.update_entry_from_slider()
                self.error_message_slider_entry.configure(text="")

            except ValueError:
                self.error_slider_value(2)

        else:
            try:
                value_three = int(self.inputchannel_Three.get())
                self.sliderchannel_Three.set(value_three)
                self.update_entry_from_slider()
                self.error_message_slider_entry.configure(text="")

            except ValueError:
                self.error_slider_value(3)

    def error_slider_value(self, x):
        self.error_message_slider_entry = ctk.CTkLabel(self, text="Please input a valid number")
        self.error_message_slider_entry.grid(row=3, column=x, sticky="n")

    def update_entry_from_slider(self, event=None):

        self.value_one = self.sliderchannel_One.get()
        self.value_two = self.sliderchannel_Two.get()
        self.value_three = self.sliderchannel_Three.get()
        self.format_value_one = "{:.1f}".format(self.value_one)
        self.format_value_two = "{:.1f}".format(self.value_two)
        self.format_value_three = "{:.1f}".format(self.value_three)
        self.inputchannel_One.delete(0, ctk.END, )
        self.inputchannel_One.insert(0, str(self.format_value_one) + " %")
        self.inputchannel_Two.delete(0, ctk.END, )
        self.inputchannel_Two.insert(0, str(self.format_value_two) + " %")
        self.inputchannel_Three.delete(0, ctk.END, )
        self.inputchannel_Three.insert(0, str(self.format_value_three) + " %")

    def toggle_status(self):
        self.status = not self.status

    def loop(self):
        if self.status:
            data_1 = float(self.format_value_one) / 100 * self.data_channel
            self.Masterchart.show_data(data=[data_1], line=self.Drawline_1)

            data_2 = float(self.format_value_two) / 100 * self.data_channel
            self.Masterchart.show_data(data=[data_2], line=self.Drawline_2)

            data_3 = float(self.format_value_three) / 100 * self.data_channel
            self.Masterchart.show_data(data=[data_3], line=self.Drawline_3)

        self.after(100, self.loop)

    def restart(self):
        super().destroy()
        restart = App(self.main_app)
        restart.mainloop()

    def destroy(self):
        self.main_app.deiconify()
        super().destroy()
        main.MainApp()


Expected behavior
With the current code it will work but if you change the y_axis_precision to 0 you can see after some time it isn't reliable.

Desktop

  • OS: Windows 11
  • Version: Latest

Reset chart : Feature

Is your feature request related to a problem? Please describe.
Just simple feature to reset the chart.

Describe the solution you'd like
Added this function to LineChart class to reset the chart

def reset(self):
    self.__reset_chart_info()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.