├── .gitignore
├── SECURITY.md
├── requirements.txt
├── PULL_REQUEST_TEMPLATE.md
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── src
└── ctkchart
│ ├── __init__.py
│ ├── FontStyle.py
│ ├── ThemeManager.py
│ ├── Utils.py
│ ├── Validate.py
│ └── CTkLine.py
├── template(s)
├── template (1).py
├── template (3).py
├── template (2).py
├── template (6).py
├── template (5).py
├── template (4).py
├── template (7).py
└── Template (8).py
├── setup.py
├── LICENSE
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── CHANGES_zh.md
├── CHANGES_en.md
├── README_zh.md
├── README.md
├── documentation
├── DOCUMENTATION_zh.md
└── DOCUMENTATION_en.md
└── Tests
└── Main - Test.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.pyd
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | customtkinter
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Pull Request Checklist
2 |
3 | - [ ] Have you tested your changes?
4 | - [ ] Have you updated the documentation?
5 | - [ ] ...
6 |
7 | ## Description
8 |
9 | Briefly describe the changes introduced by this pull request.
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/src/ctkchart/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | ctkchart: a library for create live update chart for customtkinter guis.
3 | """
4 |
5 | from .CTkLineChart import CTkLineChart
6 | from .CTkLine import CTkLine
7 |
8 | # Constants for common string values
9 | ENABLED = "enabled"
10 | DISABLED = "disabled"
11 |
12 | NORMAL = "normal"
13 | DASHED = "dashed"
14 | DOTTED = "dotted"
15 |
16 | TOP = "top"
17 | SIDE = "side"
18 |
19 | AUTO = "auto"
20 |
21 | __title__ = "ctkchart"
22 | __version__ = "2.1.9"
23 | __authors__ = ("Thisal Dilmith", "childeyouyu (有语)")
24 |
25 | __all__ = [
26 | "CTkLineChart",
27 | "CTkLine",
28 | "ENABLED",
29 | "DISABLED",
30 | "NORMAL",
31 | "DASHED",
32 | "DOTTED",
33 | "TOP",
34 | "SIDE",
35 | "AUTO",
36 | ]
37 |
--------------------------------------------------------------------------------
/template(s)/template (1).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("600+300")
7 | root.title("Line Chart")
8 | chart = ctkchart.CTkLineChart(master=root,
9 | y_axis_values = (-100,100),
10 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
11 | pointer_state="enabled"
12 | )
13 | chart.pack()
14 |
15 | line = ctkchart.CTkLine(master=chart,
16 | size=1)
17 | #point_highlight="enabled",
18 | #fill="enabled")
19 |
20 |
21 |
22 | data = [x for x in range(-100,100)]
23 | def loop():
24 | chart.show_data(line=line, data=[0, -80, -40, 100, 0, 80, 50, -50, -10,80,50,100])
25 | loop()
26 |
27 | root.mainloop()
--------------------------------------------------------------------------------
/template(s)/template (3).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("600+300")
7 | root.title("Line Chart")
8 | chart = ctkchart.CTkLineChart(master=root,
9 | y_axis_values = (-100,100),
10 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
11 | pointer_state="enabled"
12 | )
13 | chart.pack()
14 |
15 | line = ctkchart.CTkLine(master=chart,
16 | size=1,
17 | point_highlight="enabled",
18 | fill="enabled")
19 |
20 |
21 |
22 | data = [x for x in range(-100,100)]
23 | def loop():
24 | chart.show_data(line=line, data=[0, -80, -40, 100, 0, 80, 50, -50, -10,80,50,100])
25 |
26 |
27 | loop()
28 |
29 | root.mainloop()
--------------------------------------------------------------------------------
/template(s)/template (2).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("600+300")
7 | root.title("Line Chart")
8 | chart = ctkchart.CTkLineChart(master=root,
9 | y_axis_values = (-100,100),
10 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
11 | pointer_state="enabled"
12 | )
13 | chart.pack()
14 |
15 | line = ctkchart.CTkLine(master=chart,
16 | size=1,
17 | point_highlight="enabled",)
18 | #fill="enabled")
19 |
20 |
21 |
22 | data = [x for x in range(-100,100)]
23 | def loop():
24 | chart.show_data(line=line, data=[0, -80, -40, 100, 0, 80, 50, -50, -10,80,50,100])
25 |
26 |
27 | loop()
28 |
29 | root.mainloop()
--------------------------------------------------------------------------------
/template(s)/template (6).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("600+300")
7 | root.title("Line Chart")
8 | chart = ctkchart.CTkLineChart(master=root,
9 | y_axis_values = (-100,100),
10 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
11 |
12 | )
13 | chart.pack()
14 |
15 | line = ctkchart.CTkLine(master=chart,
16 | size=3,
17 | point_highlight="enabled",
18 | style="dashed",
19 | style_type=(20,5),
20 | fill="enabled")
21 |
22 |
23 |
24 | data = [x for x in range(-100,100)]
25 | def loop():
26 | chart.show_data(line=line, data=[0, -80, -40, 100, 0, 80, 50, -50, -10,80,50,100])
27 |
28 |
29 | loop()
30 |
31 | root.mainloop()
--------------------------------------------------------------------------------
/template(s)/template (5).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("600+300")
7 | root.title("Line Chart")
8 | chart = ctkchart.CTkLineChart(master=root,
9 | y_axis_values = (-100,100),
10 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
11 |
12 |
13 | )
14 | chart.pack()
15 |
16 | line = ctkchart.CTkLine(master=chart,
17 | size=1,
18 | style="dotted",
19 | style_type=(4,5),
20 | point_highlight="enabled",)
21 | #fill="enabled")
22 |
23 |
24 |
25 | data = [x for x in range(-100,100)]
26 | def loop():
27 | chart.show_data(line=line, data=[0, -80, -40, 100, 0, 80, 50, -50, -10,80,50,100])
28 |
29 |
30 | loop()
31 |
32 | root.mainloop()
--------------------------------------------------------------------------------
/template(s)/template (4).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("600+300")
7 | root.title("Line Chart")
8 | chart = ctkchart.CTkLineChart(master=root,
9 | y_axis_values = (-100,100),
10 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
11 |
12 |
13 | )
14 | chart.pack()
15 |
16 | line = ctkchart.CTkLine(master=chart,
17 | size=1,
18 | style="dashed",
19 | style_type=(10,5),
20 | point_highlight="enabled",)
21 | #fill="enabled")
22 |
23 |
24 |
25 | data = [x for x in range(-100,100)]
26 | def loop():
27 | chart.show_data(line=line, data=[0, -80, -40, 100, 0, 80, 50, -50, -10,80,50,100])
28 |
29 |
30 | loop()
31 |
32 | root.mainloop()
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | setup(
4 | name='ctkchart', # Replace with your package name
5 | version='2.1.9', # Replace with your package version
6 | author='Thisal-D', # Replace with your name
7 | author_email='', # Replace with your email
8 | description='Line-chart Widget for customtkinter, Python library for creating live updating line charts in CustomTkinter.',
9 | long_description=open('README.md').read(), # Ensure you have a README.md file
10 | long_description_content_type='text/markdown',
11 | url='https://github.com/Thisal-D/ctkchart',
12 | packages=find_packages(),
13 | classifiers=[
14 | 'Programming Language :: Python :: 3',
15 | 'License :: OSI Approved :: MIT License',
16 | 'Operating System :: OS Independent',
17 | ],
18 | python_requires='>=3.0',
19 | install_requires=[
20 | 'customtkinter', # List your package dependencies here
21 | ],
22 | include_package_data=True,
23 | )
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2024 The Python Packaging Authority
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
--------------------------------------------------------------------------------
/template(s)/template (7).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("600+300")
7 | root.title("Line Chart")
8 | chart = ctkchart.CTkLineChart(master=root,
9 | y_axis_values = (-100,100),
10 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
11 |
12 | )
13 | chart.pack()
14 |
15 | line = ctkchart.CTkLine(master=chart,
16 | size=2,
17 | point_highlight="enabled",
18 | style="dashed",
19 | style_type=(20,5),
20 | fill="disabled")
21 |
22 | line2 = ctkchart.CTkLine(master=chart,
23 | size=3,style="normal",
24 | style_type=(15,7),
25 | color=("#5dffb6","#5dffb6"),
26 | fill="enabled",
27 | fill_color = ("#5dffb6","#5dffb6")
28 | )
29 |
30 | data = [x for x in range(-100,100)]
31 | def loop():
32 | chart.show_data(line=line, data=[0, -80, -40, 100, 0, 80, 50, -50, -10,80,50,100])
33 | chart.show_data(line=line2, data=[100, -10, -90, 40, -30, 40, 90,-90, -40,-100,40,0])
34 |
35 | loop()
36 |
37 | root.mainloop()
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to ctkchart
2 |
3 | Thank you for considering contributing to ctkchart! Please follow these guidelines to contribute effectively.
4 |
5 | ## Getting Started
6 |
7 | 1. Fork the repository.
8 | 2. Clone your forked repository: `git clone https://github.com/Thisal-D/ctkchart.git`
9 | 3. Create a new branch for your changes: `git checkout -b feature-branch`
10 |
11 | ## Making Changes
12 |
13 | 1. Make your changes and ensure they follow the project's coding standards.
14 | 2. Test your changes locally.
15 | 3. Commit your changes: `git commit -m "Brief description of your changes"`
16 |
17 | ## Submitting Changes
18 |
19 | 1. Push your changes to your forked repository: `git push origin feature-branch`
20 | 2. Create a pull request on the main repository.
21 |
22 | ## Code of Conduct
23 |
24 | Please adhere to the [Code of Conduct](CODE_OF_CONDUCT.md) to maintain a respectful and inclusive community.
25 |
26 | ## Issues and Discussions
27 |
28 | If you encounter issues or have questions, please check the [issue tracker](https://github.com/Thisal-D/ctkchart/issues) or start a discussion in the [GitHub Discussions](https://github.com/Thisal-D/ctkchart/discussions) section.
29 |
30 | ## License
31 |
32 | By contributing, you agree that your contributions will be licensed under the project's [LICENSE](LICENSE).
33 |
34 | Thank you for your contribution!
--------------------------------------------------------------------------------
/template(s)/Template (8).py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import ctkchart
3 | import random
4 |
5 | #root
6 | root = ctk.CTk()
7 | root.geometry("700x400+500+300")
8 | #creating a chart
9 | chart = ctkchart.CTkLineChart(master=root,
10 | width=1700,
11 | height=800,
12 | axis_size=5,
13 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
14 | y_axis_values = (-1000,1000),
15 | y_axis_label_count=10,
16 |
17 | x_axis_section_color=("#aaaaaa","#555555"),
18 | y_axis_section_color=("#aaaaaa","#555555"),
19 |
20 | y_axis_font_color=("#454545", "#aaaaaa"),
21 | x_axis_font_color=("#454545", "#aaaaaa"),
22 | data_font_style=("arial", 17, "bold"),
23 | axis_font_style=("arial", 13, "bold"),
24 | x_axis_data_font_color=("#505050","#efefef"),
25 | y_axis_data_font_color=("#505050","#efefef"),
26 |
27 | y_space=20,
28 | x_space=20,
29 | )
30 | chart.pack(pady=40)
31 |
32 | #creating a line
33 | line1 = ctkchart.CTkLine(master=chart,
34 | size=3,
35 | style="normal",
36 |
37 | fill="enabled",
38 | point_highlight="enabled",
39 | point_highlight_size=15,
40 | )
41 |
42 |
43 |
44 |
45 | data = [x for x in range(-1000,1000)]
46 | #dipslay data (random)
47 | def loop():
48 | chart.show_data(line=line1, data=random.choices(data, k=1))
49 | root.after(500, loop)
50 | loop()
51 |
52 | root.mainloop()
--------------------------------------------------------------------------------
/src/ctkchart/FontStyle.py:
--------------------------------------------------------------------------------
1 | class FontStyle:
2 | _colors = {
3 | "black": ("30", "40"),
4 | "gray": ("90", "100"),
5 | "red": ("31", "41"),
6 | "green": ("32", "42"),
7 | "yellow": ("33", "43"),
8 | "blue": ("34", "44"),
9 | "magenta": ("35", "45"),
10 | "cyan": ("36", "46"),
11 | "white": ("37", "47"),
12 | "bright red": ("91", "101"),
13 | "bright green": ("92", "102"),
14 | "bright yellow": ("93", "103"),
15 | "bright blue": ("94", "104"),
16 | "bright magenta": ("95", "105"),
17 | "bright cyan": ("96", "106"),
18 | "bright white": ("97", "107"),
19 | }
20 |
21 | _styles = {
22 | "normal": "0",
23 | "italic": "3",
24 | "underline": "4"
25 | }
26 |
27 | @staticmethod
28 | def _get_font_style_code(fg_color: str, bg_color: str, style: str) -> str:
29 | """
30 | Returns the ANSI escape code for the given foreground color,
31 | background color, and style.
32 |
33 | Raises:
34 | ValueError: If any of the colors or style are invalid.
35 | """
36 | fg_color = fg_color.lower()
37 | bg_color = bg_color.lower()
38 | style = style.lower()
39 |
40 | if fg_color not in FontStyle._colors:
41 | raise ValueError(f"Invalid foreground color: {fg_color}")
42 | if bg_color not in FontStyle._colors:
43 | raise ValueError(f"Invalid background color: {bg_color}")
44 | if style not in FontStyle._styles:
45 | raise ValueError(f"Invalid style: {style}")
46 |
47 | fg_code = FontStyle._colors[fg_color][0]
48 | bg_code = FontStyle._colors[bg_color][1]
49 | style_code = FontStyle._styles[style]
50 |
51 | return f"\x1b[{style_code};{fg_code};{bg_code}m"
52 |
53 | @staticmethod
54 | def _apply(value: str, fg_color: str, bg_color: str, style: str = "normal") -> str:
55 | """
56 | Apply the font style to the given string.
57 |
58 | Args:
59 | value (str): The text to style.
60 | fg_color (str): Foreground color name.
61 | bg_color (str): Background color name.
62 | style (str, optional): Style name. Defaults to "normal".
63 |
64 | Returns:
65 | str: The styled text with ANSI escape codes.
66 | """
67 | code = FontStyle._get_font_style_code(fg_color, bg_color, style)
68 | reset = "\x1b[0m"
69 | return f"{code}{value}{reset}"
70 |
--------------------------------------------------------------------------------
/src/ctkchart/ThemeManager.py:
--------------------------------------------------------------------------------
1 | import customtkinter as ctk
2 | import time
3 | import threading
4 | from typing import List, Tuple, Any, Union
5 |
6 |
7 | class ThemeManager:
8 | running_state: bool = False
9 | child_objects: List[Any] = []
10 | theme: str = "-"
11 |
12 | @staticmethod
13 | def get_color_by_theme(color: Union[Tuple[str, str], str]) -> str:
14 | """
15 | Returns the appropriate color based on the current theme.
16 |
17 | Args:
18 | color (Tuple[str, str] | str): A tuple of (light_color, dark_color) or a single color string.
19 |
20 | Returns:
21 | str: The color corresponding to the current theme.
22 | """
23 | if isinstance(color, tuple):
24 | return color[0] if ThemeManager.theme == "Light" else color[1]
25 | return color
26 |
27 | @staticmethod
28 | def theme_tracker() -> None:
29 | """
30 | Monitors and applies theme changes across all registered widgets.
31 | """
32 | while ThemeManager.child_objects:
33 | current_theme = ctk.get_appearance_mode()
34 | if current_theme != ThemeManager.theme:
35 | ThemeManager.theme = current_theme
36 | for widget in ThemeManager.child_objects:
37 | try:
38 | widget._CTkLineChart__configure_theme_mode()
39 | except Exception as e:
40 | print(f"[ThemeManager] Theme update failed for widget: {e}")
41 | time.sleep(1)
42 |
43 | ThemeManager.running_state = False
44 |
45 | @staticmethod
46 | def run() -> None:
47 | """
48 | Starts the background theme tracking thread if not already running.
49 | """
50 | if not ThemeManager.running_state:
51 | ThemeManager.running_state = True
52 | thread = threading.Thread(target=ThemeManager.theme_tracker, daemon=True)
53 | thread.start()
54 |
55 | @staticmethod
56 | def bind_widget(widget: Any) -> None:
57 | """
58 | Registers a widget with the theme manager.
59 |
60 | Args:
61 | widget (Any): Widget instance with a `_CTkLineChart__configure_theme_mode` method.
62 | """
63 | ThemeManager.child_objects.append(widget)
64 | if not ThemeManager.running_state:
65 | ThemeManager.run()
66 |
67 | @staticmethod
68 | def unbind_widget(widget: Any) -> None:
69 | """
70 | Unregisters a widget from the theme manager.
71 |
72 | Args:
73 | widget (Any): The widget to remove.
74 | """
75 | try:
76 | ThemeManager.child_objects.remove(widget)
77 | except ValueError:
78 | print(f"[ThemeManager] Widget not found.")
79 | except Exception as e:
80 | print(f"[ThemeManager] Error removing widget: {e}")
81 |
--------------------------------------------------------------------------------
/src/ctkchart/Utils.py:
--------------------------------------------------------------------------------
1 | import tkinter
2 | from typing import Union, Tuple, Any, List
3 |
4 |
5 | class Utils:
6 | __scaling_factor = 1 # Private class variable to scale dimensions (can be adjusted if needed)
7 |
8 | @staticmethod
9 | def _required_width(text: Any, font: Tuple[str, int, str]) -> float:
10 | """
11 | Calculate the required width for a given text and font.
12 |
13 | Args:
14 | text (Any): The text to measure.
15 | font (Tuple[str, int, str]): The font used for the label.
16 |
17 | Returns:
18 | float: The required width.
19 | """
20 | label = tkinter.Label(font=font, text=str(text))
21 | return label.winfo_reqwidth() / Utils.__scaling_factor
22 |
23 | @staticmethod
24 | def _required_height(text: Any, font: Tuple[str, int, str]) -> float:
25 | """
26 | Calculate the required height for a given text and font.
27 |
28 | Args:
29 | text (Any): The text to measure.
30 | font (Tuple[str, int, str]): The font used for the label.
31 |
32 | Returns:
33 | float: The required height.
34 | """
35 | label = tkinter.Label(font=font, text=str(text))
36 | return label.winfo_reqheight() / Utils.__scaling_factor
37 |
38 | @staticmethod
39 | def _format_float_with_precision(value: Union[float, int], decimals: int) -> str:
40 | """
41 | Format a float value to a fixed number of decimal places with trailing zeros.
42 |
43 | Args:
44 | value (float | int): The value to format.
45 | decimals (int): The number of decimal places.
46 |
47 | Returns:
48 | str: The formatted string.
49 | """
50 | if decimals > 0:
51 | value = round(float(value), decimals)
52 | value_str = str(value)
53 | decimals_part = value_str.split(".")[-1]
54 | padded = value_str + "0" * (decimals - len(decimals_part))
55 | return padded
56 | return str(int(value))
57 |
58 | @staticmethod
59 | def _get_max_required_label_width(data: List[Any], font: Tuple[str, int, str]) -> float:
60 | """
61 | Get the maximum required width among multiple text labels.
62 |
63 | Args:
64 | data (List[Any]): A list of text values.
65 | font (Tuple[str, int, str]): Font for the labels.
66 |
67 | Returns:
68 | float: Maximum required width.
69 | """
70 | return max(Utils._required_width(d, font) for d in data)
71 |
72 | @staticmethod
73 | def _get_max_required_label_height(data: List[Any], font: Tuple[str, int, str]) -> float:
74 | """
75 | Get the maximum required height among multiple text labels.
76 |
77 | Args:
78 | data (List[Any]): A list of text values.
79 | font (Tuple[str, int, str]): Font for the labels.
80 |
81 | Returns:
82 | float: Maximum required height.
83 | """
84 | return max(Utils._required_height(d, font) for d in data)
85 |
86 | @staticmethod
87 | def _sort_tuple(values: Tuple[int, ...]) -> Tuple[int, ...]:
88 | """
89 | Sort and deduplicate a tuple of integers.
90 |
91 | Args:
92 | values (Tuple[int, ...]): The input tuple.
93 |
94 | Returns:
95 | Tuple[int, ...]: A sorted, unique tuple.
96 | """
97 | return tuple(sorted(set(values)))
98 |
99 | @staticmethod
100 | def _to_int(value: Union[int, str]) -> int:
101 | """
102 | Convert a value to integer.
103 |
104 | Args:
105 | value (int | str): The value to convert.
106 |
107 | Returns:
108 | int: The integer result.
109 | """
110 | return int(value)
111 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | .
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/CHANGES_zh.md:
--------------------------------------------------------------------------------
1 | [](CHANGES_en.md)
2 |
3 | ## v2.1.7
4 |
5 | - ### 新方法添加到 `CTkLineChart` 对象
6 | | 方法名 | 描述 | 参数 | 返回类型 |
7 | |------------------------------|------------------------------------------------------------|------------------------------------------|-----------------|
8 | | `get_lines_data` | 获取指定范围内所有线条的数据点,可以选择步长值。 | start: `int` end: `int` step: `int` | `Dict[ctkchart.CTkLine, Tuple[int]]` |
9 | | `get_line_data` | 获取指定范围和步长值下某一条线的数据点。 | line: `ctkchart.CTkLine` start: `int` end: `int` step: `int` | `Tuple[int \| float]` |
10 | | `get_x_axis_visible_point_count` | 获取X轴上可见数据点的最大数量。 | - | `int` |
11 | | `get_lines_visible_data` | 获取所有线条当前可见的数据点,基于最大数据长度和可见点数。 | - | `Dict[ctkchart.CTkLine, Tuple[int \| float]]` |
12 | | `get_line_visible_data` | 获取某一条线当前可见的数据点。 | line: `ctkchart.CTkLine` | `Tuple[int \| float]` |
13 |
14 | - ### 新方法添加到 `CTkLine` 对象
15 | | 方法名 | 描述 | 参数 | 返回类型 |
16 | |------------------------------|------------------------------------------------------------|------------------------------------------|-----------------|
17 | | `get_data` | 获取指定范围的数据点,可以选择步长值。如果没有提供参数,将返回所有可用数据。 | start: `int` end: `int` step: `int` | `Tuple[int \| float]` |
18 | | `get_current_visible_data` | 根据所有线条的最大数据长度和最大可见点数,返回当前可见的数据点。 | - | `Tuple[int \| float]` |
19 | | `get_x_axis_visible_point_count` | 获取X轴上可见数据点的最大数量。 | - | `int` |
20 |
21 |
22 | ## v2.1.5
23 |
24 | - ### 新增方法到 `CTkLineChart` 对象
25 | | 方法名称 | 描述 | 参数 | 返回类型 |
26 | |------------------|------------------------------------------------------------|----------------|-------------|
27 | | `clear_data` | 清除图表中所有线的数据,确保只保留最新的可见数据点。如果数据点总数超过最大可见点,则会从每条线的数据中移除旧数据。此方法确保图表仅显示基于最大可见范围的相关数据部分。 | - | `None` |
28 |
29 | - ### 新增方法到 `CTkLine` 对象
30 | | 方法名称 | 描述 | 参数 | 返回类型 |
31 | |------------------|------------------------------------------------------------|----------------|-------------|
32 | | `clear_data` | 清除特定线的数据,确保只保留最新的可见数据点。如果线的数据超过最大可见点,则会修剪旧数据。此方法允许每条线独立清除其数据,确保它始终保持在可见范围内。 | - | `None` |
33 |
34 | ---
35 |
36 | ## v2.1.4
37 |
38 | - ### 新增方法到 `CTkLineChart` 对象
39 | | 方法名称 | 描述 | 参数 | 返回类型 |
40 | |------------------|------------------------------------------------------------|----------------|-------------|
41 | | `get_line_area` | 获取特定线的区域大小 | line: `ctkchart.CTkLine` | `float` |
42 | | `get_lines_area` | 获取所有线的区域大小 | - | `float` |
43 |
44 | ---
45 |
46 | ## v2.1.3
47 |
48 | - ### 新增方法到 `CTkLineChart` 对象
49 | | 方法名称 | 描述 | 参数 | 返回类型 |
50 | |------------------|------------------------------------------------------------|----------------|-------------|
51 | | `destroy` | 销毁线图及其所有线 | - | `None` |
52 |
53 | - ### 新增方法到 `CTkLine` 对象
54 | | 方法名称 | 描述 | 参数 | 返回类型 |
55 | |------------------|------------------------------------------------------------|----------------|-------------|
56 | | `destroy` | 销毁线对象 | - | `None` |
57 |
58 | ---
59 |
60 | ## v2.1.2
61 |
62 | - ### 新增方法到 `CTkLine` 对象
63 |
64 | | 方法名称 | 描述 | 参数 | 返回类型 |
65 | |------------------|------------------------------------------------|------------------------------------------|-------------|
66 | | `cget` | 获取指定参数的值 | attribute_name: `str \| "__all__"` | `any` |
67 | | `set_visible` | 更改线的可见性 | state: `bool` | `None` |
68 | | `get_visibility` | 获取线的可见性 | - | `bool` |
69 |
70 | - ### 新增方法到 `CTkLineChart` 对象
71 |
72 | | 方法名称 | 描述 | 参数 | 返回类型 |
73 | |------------------------|------------------------------------------------|--------------------------------------------------|-------------|
74 | | `set_lines_visibility` | 更改所有线的可见性 | state: `bool` | `None` |
75 | | `set_line_visibility` | 更改特定线的可见性 | line: `ctkchart.CTkLine` state: `bool` | `None` |
76 | | `get_line_visibility` | 获取特定线的可见性 | line: `ctkchart.CTkLine` | `bool` |
77 | | `cget` | 获取指定参数的值 | attribute_name: `str \| "__all__"` | `any` |
78 | | `place_info` | 获取位置相关信息 | attribute_name: `str \| "__all__"` | `any` |
79 | | `pack_info` | 获取打包相关信息 | attribute_name: `str \| "__all__"` | `any` |
80 | | `grid_info` | 获取网格相关信息 | attribute_name: `str \| "__all__"` | `any` |
81 |
82 | - ### 移除 `CTkLineChart` 对象的方法
83 |
84 | | 方法名称 | 描述 | 参数 | 返回类型 |
85 | |-------------|----------------------|----------------------------------------------|-------------|
86 | | hide_all | 隐藏所有的线 | state: `bool` | None |
87 | | hide | 隐藏特定的线 | line: `ctkchart.CTkLine` state: `bool` | None |
88 |
--------------------------------------------------------------------------------
/CHANGES_en.md:
--------------------------------------------------------------------------------
1 | [](CHANGES_zh.md)
2 |
3 |
4 | ## v2.1.7
5 |
6 | - ### New Methods Added to `CTkLineChart` Object
7 | | Method Name | Description | Parameters | Return Type |
8 | |------------------------------|------------------------------------------------------------|------------------------------------------|-----------------|
9 | | `get_lines_data` | Retrieves data points for all lines within a specified range with an optional step value. | start: `int` end: `int` step: `int` | `Dict[ctkchart.CTkLine, Tuple[int]]` |
10 | `get_line_data` | Retrieves data points for a specific line within a specified range and step. | line: `ctkchart.CTkLine` start: `int` end: `int` step: `int` | `Tuple[int \| float]` |
11 | | `get_x_axis_visible_point_count` | Retrieves the maximum number of data points that can be visible along the X-axis. | - | `int` |
12 | | `get_lines_visible_data` | Retrieves currently visible data points for all lines based on the maximum data length and visible points. | - | `Dict[ctkchart.CTkLine, Tuple[int \| float]]` |
13 | | `get_line_visible_data` | Retrieves currently visible data points for a specific line. | line: `ctkchart.CTkLine` | `Tuple[int \| float]` |
14 |
15 |
16 |
17 | - ### New Methods Added to `CTkLine` Object
18 | | Method Name | Description | Parameters | Return Type |
19 | |------------------------------|------------------------------------------------------------|---------------------|-----------------|
20 | | `get_data` | Retrieves data points from a specified range with an optional step value. If no parameters are given, it returns all available data. | start: `int` end: `int` step: `int` | `Tuple[int \| float]` |
21 | | `get_current_visible_data` | Returns the currently visible data points based on the maximum data length across all lines and the maximum number of visible points. | - | `Tuple[int \| float]` |
22 | | `get_x_axis_visible_point_count` | Retrieves the maximum number of data points that can be visible along the X-axis. | - | `int` |
23 |
24 |
25 | ## v2.1.5
26 |
27 | - ### New Method Added to `CTkLineChart` Object
28 | | Method Name | Description | Parameters | Return Type |
29 | |------------------|------------------------------------------------------------|----------------|-------------|
30 | | `clear_data` | Clears the data for all lines within the chart, ensuring that only the most recent visible data points are retained. If the total data points exceed the maximum visible points, the older data is removed from each line's data. This method ensures that the chart displays only the relevant portion of data based on the maximum visible range. | - | `None` |
31 |
32 | - ### New Method Added to `CTkLine` Object
33 | | Method Name | Description | Parameters | Return Type |
34 | |------------------|------------------------------------------------------------|----------------|-------------|
35 | | `clear_data` | Clears the data for a specific line, ensuring that only the most recent visible data points are retained. If the line's data exceeds the maximum visible points, the older data is trimmed. This method allows each line to independently clean its data, ensuring it remains within the visible range. | - | `None` |
36 |
37 | ---
38 |
39 | ## v2.1.4
40 |
41 | - ### New Method Added to `CTkLineChart` Object
42 | | Method Name | Description | Parameters | Return Type |
43 | |------------------|------------------------------------------------------------|----------------|-------------|
44 | | `get_line_area` | Get the are of specific line | line: `ctkchart.CTkLine` | `float` |
45 | | `get_lines_area` | Get the are of all lines | - | `float` |
46 |
47 | ---
48 |
49 | ## v2.1.3
50 |
51 | - ### New Method Added to `CTkLineChart` Object
52 | | Method Name | Description | Parameters | Return Type |
53 | |------------------|------------------------------------------------------------|----------------|-------------|
54 | | `destroy` | Destroy the line chart, along with its lines | - | `None` |
55 |
56 | - ### New Method Added to `CTkLine` Object
57 | | Method Name | Description | Parameters | Return Type |
58 | |------------------|------------------------------------------------------------|----------------|-------------|
59 | | `destroy` | Destroy the line object | - | `None` |
60 |
61 | ---
62 |
63 | ## v2.1.2
64 |
65 | - ### New Method Added to `CTkLine` Object
66 |
67 | | Method Name | Description | Parameters | Return Type |
68 | |------------------|------------------------------------------------|------------------------------------------|-------------|
69 | | `cget` | Get the value of the specified parameter | attribute_name: `str \| "__all__"` | `any` |
70 | | `set_visible` | Change the visibility of the line | state: `bool` | `None` |
71 | | `get_visibility` | Get the visibility of the line | - | `bool` |
72 |
73 | - ### New Methods Added to CTkLineChart Object
74 |
75 | | Method Name | Description | Parameters | Return Type |
76 | |------------------------|------------------------------------------------|--------------------------------------------------|-------------|
77 | | `set_lines_visibility` | Change the visibility of all the lines | state: `bool` | `None` |
78 | | `set_line_visibility` | Change the visibility of a specific line | line: `ctkchart.CTkLine` state: `bool` | `None` |
79 | | `get_line_visibility` | Get the visibility of a specific line | line: `ctkchart.CTkLine` | `bool` |
80 | | `cget` | Get the value of the specified parameter | attribute_name: `str \| "__all__"` | `any` |
81 | | `place_info` | Get info about place | attribute_name: `str \| "__all__"` | `any` |
82 | | `pack_info` | Get info about pack | attribute_name: `str \| "__all__"` | `any` |
83 | | `grid_info` | Get info about grid | attribute_name: `str \| "__all__"` | `any` |
84 |
85 | - ### Removed Methods in CTkLineChart Object
86 |
87 | | Method Name | Description | Parameters | Return Type |
88 | |-------------|----------------------|----------------------------------------------|-------------|
89 | | hide_all | Hide all the lines | state: `bool` | None |
90 | | hide | hide a specific line | line: `ctkchart.CTkLine` state: `bool` | None |
--------------------------------------------------------------------------------
/src/ctkchart/Validate.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple, Any
2 | from .FontStyle import FontStyle
3 | import tkinter
4 |
5 |
6 | class Validate:
7 | @staticmethod
8 | def _error_font(value: str) -> str:
9 | """Return a formatted error message."""
10 | return FontStyle._apply(value, "red", "black", "underline")
11 |
12 | @staticmethod
13 | def _var_font(value: str) -> str:
14 | """Return a formatted variable name."""
15 | return FontStyle._apply(value, "green", "black", "italic")
16 |
17 | @staticmethod
18 | def _is_tuple(value: Any, var: str) -> None:
19 | """Check if value is a tuple."""
20 | if type(value) is not tuple:
21 | raise TypeError(f"{Validate._var_font(var)} {Validate._error_font('must be tuple.')}")
22 |
23 | @staticmethod
24 | def _is_list(value: Any, var: str) -> None:
25 | """Check if value is a list."""
26 | if type(value) is not list:
27 | raise TypeError(f"{Validate._var_font(var)} {Validate._error_font('must be list.')}")
28 |
29 | @staticmethod
30 | def _is_int(value: Any, var: str) -> None:
31 | """Check if value is an integer."""
32 | if type(value) is not int:
33 | raise TypeError(f"{Validate._var_font(var)} {Validate._error_font('must be int.')}")
34 |
35 | @staticmethod
36 | def _is_bool(value: Any, var: str) -> None:
37 | """Check if value is a boolean."""
38 | if type(value) is not bool:
39 | raise TypeError(f"{Validate._var_font(var)} {Validate._error_font('must be bool.')}")
40 |
41 | @staticmethod
42 | def _is_str(value: Any, var: str) -> None:
43 | """Check if value is a string."""
44 | if type(value) is not str:
45 | raise TypeError(f"{Validate._var_font(var)} {Validate._error_font('must be str.')}")
46 |
47 | @staticmethod
48 | def _is_valid_color(value: Any, var: str) -> None:
49 | """Check if value is a valid color string or tuple."""
50 | valid = True
51 | if type(value) is tuple and len(value) == 2:
52 | try:
53 | tkinter.Label(bg=value[0])
54 | tkinter.Label(bg=value[1])
55 | except:
56 | valid = False
57 | elif type(value) is str:
58 | try:
59 | tkinter.Label(bg=value)
60 | except:
61 | valid = False
62 | else:
63 | valid = False
64 | if not valid:
65 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be valid color. eg:- '#ff0000'/ 'red'/ ('#ffffff', '#000000')")}''')
66 |
67 | @staticmethod
68 | def _is_valid_font(value: Any, var: str) -> None:
69 | """Check if value is a valid font tuple."""
70 | Validate._is_tuple(value, var)
71 | try:
72 | tkinter.Label(font=value)
73 | except:
74 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be valid font. eg:- ('arial',10,'bold')")}''')
75 |
76 | @staticmethod
77 | def _is_valid_function(value: Any, var: str) -> None:
78 | """Check if value is a callable function or None."""
79 | if not callable(value) and value is not None:
80 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("must be function with two parameters or *args.")}''')
81 |
82 | @staticmethod
83 | def _is_valid_x_axis_indices(values: Tuple[Any, ...], indices: Tuple[int, ...], var: str) -> None:
84 | """Validate x-axis indices within bounds."""
85 | if indices is not None:
86 | Validate._is_tuple(indices, var)
87 | Validate._is_valid_indices(indices, var)
88 | for index in indices:
89 | if index >= len(values):
90 | raise IndexError(f'''{Validate._var_font(var)} {Validate._error_font("values must be lower than length of x_axis_values.")}''')
91 |
92 | @staticmethod
93 | def _is_valid_x_axis_label_count(values: Any, var: str) -> None:
94 | """Check x-axis label count is an int."""
95 | if values is not None:
96 | Validate._is_int(values, var)
97 |
98 | @staticmethod
99 | def _is_valid_style_type(value: Any, var: str) -> None:
100 | """Check style type as a tuple of two integers."""
101 | Validate._is_tuple(value, var)
102 | if len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int):
103 | return
104 | elif len(value) != 2:
105 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("length must be two.")}''')
106 | else:
107 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("values must be integers.")}''')
108 |
109 | @staticmethod
110 | def _is_valid_data_position(value: Any, var: str) -> None:
111 | """Check if data position is 'top' or 'side'."""
112 | Validate._is_str(value, var)
113 | if value not in ("top", "side"):
114 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be 'top' or 'side'.")}''')
115 |
116 | @staticmethod
117 | def _is_valid_line_style(value: Any, var: str) -> None:
118 | """Check line style is 'normal', 'dotted' or 'dashed'."""
119 | Validate._is_str(value, var)
120 | if value not in ("normal", "dotted", "dashed"):
121 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be 'normal' or 'dotted' or 'dashed'.")}''')
122 |
123 | @staticmethod
124 | def _is_valid_section_style(value: Any, var: str) -> None:
125 | """Check section style is 'normal' or 'dashed'."""
126 | Validate._is_str(value, var)
127 | if value not in ("normal", "dashed"):
128 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be 'normal' or 'dashed'.")}''')
129 |
130 | @staticmethod
131 | def _is_valid_x_axis_point_spacing(value: Any, var: str) -> None:
132 | """Check point spacing is integer or 'auto'."""
133 | if isinstance(value, int) or (isinstance(value, str) and value == "auto"):
134 | return
135 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("must be integer or 'auto'.")}''')
136 |
137 | @staticmethod
138 | def _is_valid_pointer_state_lock(value: Any, var: str) -> None:
139 | """Check if pointer lock state is valid."""
140 | Validate._is_str(value, var)
141 | if value not in ("enabled", "disabled"):
142 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be 'disabled' or 'enabled'.")}''')
143 |
144 | @staticmethod
145 | def _is_valid_line_highlight(value: Any, var: str) -> None:
146 | """Check if line highlight is enabled or disabled."""
147 | Validate._is_str(value, var)
148 | if value not in ("enabled", "disabled"):
149 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be 'disabled' or 'enabled'.")}''')
150 |
151 | @staticmethod
152 | def _is_valid_line_fill(value: Any, var: str) -> None:
153 | """Check if line fill is enabled or disabled."""
154 | Validate._is_str(value, var)
155 | if value not in ("enabled", "disabled"):
156 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be 'disabled' or 'enabled'.")}''')
157 |
158 | @staticmethod
159 | def _is_valid_y_axis_values(value: Any, var: str) -> None:
160 | """Validate y-axis value tuple with two ascending numbers."""
161 | Validate._is_tuple(value, var)
162 | if value == (None, None):
163 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be provide.")}''')
164 | if len(value) != 2:
165 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("length must be two.")}''')
166 | if not all(isinstance(v, (int, float)) for v in value):
167 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("values must be integer or float.")}''')
168 | if value[0] >= value[1]:
169 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("first value must be less than second value.")}''')
170 |
171 | @staticmethod
172 | def _is_valid_x_axis_values(value: Any, var: str) -> None:
173 | """Check x-axis values are valid and not placeholders."""
174 | if value == (None, "None", None, "None"):
175 | raise ValueError(f'''{Validate._var_font(var)} {Validate._error_font("must be provide.")}''')
176 | Validate._is_tuple(value, var)
177 |
178 | @staticmethod
179 | def _is_valid_ctk_line(value: Any, var: str) -> None:
180 | """Check if value is instance of CTkLine."""
181 | from .CTkLine import CTkLine
182 | if type(value) is not CTkLine:
183 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("type must be ctkchart.CTkLine")}''')
184 |
185 | @staticmethod
186 | def _is_valid_ctk_line_chart(value: Any, var: str) -> None:
187 | """Check if value is instance of CTkLineChart."""
188 | from .CTkLineChart import CTkLineChart
189 | if type(value) is not CTkLineChart:
190 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("type must be ctkchart.CTkLineChart")}''')
191 |
192 | @staticmethod
193 | def _is_valid_data(value: Any, var: str) -> None:
194 | """Ensure list contains only numeric values."""
195 | Validate._is_list(value, var)
196 | if not all(isinstance(v, (int, float)) for v in value):
197 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("all values in the list should be either int or float.")}''')
198 |
199 | @staticmethod
200 | def _is_valid_indices(value: Any, var: str) -> None:
201 | """Ensure all indices are integers."""
202 | if not all(isinstance(v, int) for v in value):
203 | raise TypeError(f'''{Validate._var_font(var)} {Validate._error_font("all values should be int.")}''')
204 |
205 | @staticmethod
206 | def _invalid_cget(var: str) -> None:
207 | """Raise error for invalid attribute access."""
208 | raise TypeError(f'''{Validate._var_font(str(var))} {Validate._error_font("Invalid attribute.")}''')
209 |
210 | @staticmethod
211 | def _invalid_ctk_line(line) -> None:
212 | """Raise error when line not part of chart."""
213 | raise ValueError(f'''{Validate._var_font(str(line))} {Validate._error_font("The line is not part of this line chart.")}''')
214 |
215 | @staticmethod
216 | def _invalid_master(value):
217 | """Raise error for invalid chart master."""
218 | raise ValueError(f'''{Validate._var_font(str(value))} {Validate._error_font("Invalid Master for chart.")}''')
219 |
220 | @staticmethod
221 | def _master_att_not_provide_for_line(value):
222 | """Raise error when master not provided for line."""
223 | raise ValueError(f'''{Validate._var_font(str(value))} {Validate._error_font("master must be provide for CTkLine")}''')
224 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | [](README.md)
2 |
3 |
4 |
5 | [](https://snyk.io/advisor/python/ctkchart)
6 |
7 | # ctkchart
8 |
9 | [](https://pypi.org/project/ctkchart/)
10 |
11 | [](https://pepy.tech/project/ctkchart)  [](https://pepy.tech/project/ctkchart) [](https://pepy.tech/project/ctkchart)
12 |
13 |
14 | 
15 | 
16 |
17 |
18 |
19 | **ctkchart 是一个用于在 customtkinter 中创建实时更新折线图的 Python 库。 **
20 |
21 | ---
22 |
23 | ### 特性
24 |
25 | - **实时更新**: 显示带有实时数据的折线图。
26 | - **多条线**: 支持在同一图表上绘制多条线,便于比较。
27 | - **颜色定制**: 自定义颜色以匹配您的应用程序设计或数据表示。
28 | - **动态颜色变化**: 实现暗模式和亮模式下的动态颜色变化。
29 | - **字体定制**: 调整文本元素的字体以增强可读性。
30 | - **尺寸定制**: 根据不同显示尺寸和布局自定义图表尺寸。
31 |
32 | [**查看最新更新 | 更改**](CHANGES_zh.md)
33 |
34 | ---
35 |
36 | ### 导入与安装
37 | * **安装**
38 | ```
39 | pip install ctkchart
40 | ```
41 |
42 | * **导入**
43 | ``` python
44 | import ctkchart
45 | ```
46 |
47 | ---
48 |
49 | ### 简单示例
50 | - **导入库**
51 | ``` python
52 | import tkchart
53 | ```
54 |
55 | - **创建折线图并放置图表**
56 | ``` python
57 | chart = ctkchart.CTkLineChart(
58 | master=root,
59 | x_axis_values=("a", "b", "c", "d", "e", "f"),
60 | y_axis_values=(100, 900)
61 | )
62 | chart.place(x=10, y=10)
63 | ```
64 |
65 | - **创建折线**
66 | ``` python
67 | line = ctkchart.CTkLine(master=chart)
68 | ```
69 |
70 | - **显示数据**
71 | 使用循环显示数据
72 | ``` python
73 | def loop():
74 | while True:
75 | random_data = random.choice(range(100, 900))
76 | chart.show_data(line=line, data=[random_data])
77 | time.sleep(1)
78 |
79 | #调用线程
80 | theading.Thread(target=loop).start()
81 | ```
82 |
83 | ---
84 |
85 | ### 链接
86 |
87 | - **文档 :** [文档](documentation)
88 | - [英文文档](documentation/DOCUMENTATION_en.md)
89 | - [中文文档](documentation/DOCUMENTATION_zh.md)
90 | - **Python 官方 :** [ctkchart](https://pypi.org/project/ctkchart/)
91 |
92 | ---
93 |
94 | ### 您可以完成的任务
95 |
96 | - **简单示例**
97 |
98 | https://github.com/Thisal-D/ctkchart/assets/93121062/6f1e844f-d51c-467a-a3dc-ee03fea78fc9
99 |
100 | ``` python
101 | import customtkinter as ctk # 导入 customtkinter 库作为 ctk
102 | import ctkchart # 导入 ctkchart 模块用于创建图表
103 | import random # 导入 random 模块用于生成随机数据
104 | import threading # 导入 threading 模块用于并发执行任务
105 | import time # 导入 time 模块用于添加延时
106 |
107 | # 创建根窗口并配置
108 | root = ctk.CTk()
109 | root.configure(fg_color="#0d1117")
110 | root.geometry("720x430+200+200")
111 |
112 | # 创建折线图控件
113 | line_chart = ctkchart.CTkLineChart(
114 | master=root, # 设置根窗口为父容器
115 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X轴值
116 | y_axis_values=(0, 1000) # Y轴值(范围)
117 | )
118 |
119 | line_chart.pack(pady=15) # 将折线图控件放入根窗口
120 |
121 | # 创建折线
122 | line = ctkchart.CTkLine(master=line_chart) # 设置折线图为父容器
123 |
124 | def display_data():
125 | """函数用于持续在折线图上显示随机数据。"""
126 | while True:
127 | random_data = [random.choice(range(0, 1000))] # 生成 0 到 1000 之间的随机数据
128 | line_chart.show_data(line=line, data=random_data) # 在折线图上显示随机数据
129 | time.sleep(0.5) # 在下一次迭代之前暂停 0.5 秒
130 |
131 | # 在新线程中调用 display_data 函数
132 | threading.Thread(target=display_data).start()
133 |
134 | # 启动主事件循环
135 | root.mainloop()
136 | ```
137 | ---
138 |
139 | - **简单风格**
140 |
141 | https://github.com/Thisal-D/ctkchart/assets/93121062/afe56452-68c3-44f0-9c67-2ab6f6910f6e
142 |
143 | ``` python
144 | import customtkinter as ctk # 导入 customtkinter 库作为 ctk
145 | import ctkchart # 导入 ctkchart 模块用于创建图表
146 | import random # 导入 random 模块用于生成随机数据
147 | import threading # 导入 threading 模块用于并发执行任务
148 | import time # 导入 time 模块用于添加延时
149 |
150 | # 创建根窗口并配置
151 | root = ctk.CTk()
152 | root.configure(fg_color="#0d1117")
153 | root.geometry("720x430+200+200")
154 |
155 | # 创建折线图控件
156 | line_chart = ctkchart.CTkLineChart(
157 | master=root, # 设置根窗口为父容器
158 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X轴值
159 | y_axis_values=(0, 1000), # Y轴值(范围)
160 | y_axis_label_count=10, # 设置Y轴标签数量为10
161 | )
162 |
163 | line_chart.pack(pady=15) # 将折线图控件放入根窗口
164 |
165 | # 创建折线
166 | line = ctkchart.CTkLine(
167 | master=line_chart, # 设置折线图为父容器
168 | size=2, # 设置折线宽度为 2
169 | fill="enabled" # 启用填充效果
170 | )
171 |
172 | def display_data():
173 | """函数用于持续在折线图上显示随机数据。"""
174 | while True:
175 | random_data = [random.choice(range(0, 1000))] # 生成 0 到 1000 之间的随机数据
176 | line_chart.show_data(line=line, data=random_data) # 在折线图上显示随机数据
177 | time.sleep(0.5) # 在下一次迭代之前暂停 0.5 秒
178 |
179 | # 在新线程中调用 display_data 函数
180 | threading.Thread(target=display_data).start()
181 |
182 | # 启动主事件循环
183 | root.mainloop()
184 | ```
185 | ---
186 |
187 | - **两条线,不同的线型**
188 |
189 | https://github.com/Thisal-D/ctkchart/assets/93121062/9bc35a39-a8ca-4942-9fc7-a1c89d1bd1bc
190 |
191 | ```python
192 | import customtkinter as ctk # 导入 customtkinter 库作为 ctk
193 | import ctkchart # 导入 ctkchart 模块用于创建图表
194 | import random # 导入 random 模块用于生成随机数据
195 | import threading # 导入 threading 模块用于并发运行任务
196 | import time # 导入 time 模块用于添加延迟
197 |
198 | # 创建根窗口并配置
199 | root = ctk.CTk()
200 | root.configure(fg_color=("#ffffff", "#0d1117"))
201 | root.geometry("720x430+200+200")
202 |
203 | # 创建线性图表小部件
204 | line_chart = ctkchart.CTkLineChart(
205 | master=root, # 设置根窗口为主窗口
206 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X轴的值
207 | y_axis_values=(0, 1000), # Y轴的值(范围)
208 | y_axis_label_count=10, # 设置Y轴标签数量为10
209 | )
210 |
211 | line_chart.pack(pady=15) # 将线图部件打包到根窗口中
212 |
213 | line1 = ctkchart.CTkLine(
214 | master=line_chart, # 设置线图的主窗口
215 | color=("#5dffb6", "#5dffb6"), # 轻主题为#5dffb6,暗主题为#5dffb6
216 | size=2, # 设置线的大小为2
217 | style="dashed", # 将线的样式更改为虚线
218 | style_type=(10, 5), # 设置虚线的宽度和虚线之间的间隔
219 | )
220 |
221 | line2 = ctkchart.CTkLine(
222 | master=line_chart, # 设置线图的主窗口
223 | color=("#FFBAD2", "#FFBAD2"), # 轻主题为#FFBAD2,暗主题为#FFBAD2
224 | size=2, # 设置线的大小为2
225 | point_highlight="enabled", # 启用点高亮
226 | point_highlight_color=("#FFBAD2", "#FFBAD2"), # 设置高亮颜色
227 | )
228 |
229 | def display_data():
230 | """函数:持续在图表上显示随机数据。"""
231 | while True:
232 | random_data = [random.choice(range(0, 1000))] # 生成 0 到 1000 之间的随机数据
233 | line_chart.show_data(line=line1, data=random_data) # 显示数据在 line1 上
234 | random_data = [random.choice(range(0, 1000))] # 生成新的随机数据
235 | line_chart.show_data(line=line2, data=random_data) # 显示数据在 line2 上
236 | time.sleep(0.5) # 暂停 0.5 秒钟再进行下一次迭代
237 |
238 | # 以独立线程运行 display_data 函数
239 | threading.Thread(target=display_data).start()
240 |
241 | # 启动主事件循环
242 | root.mainloop()
243 | ```
244 |
245 | ---
246 |
247 | - **三条线,不同的线型**
248 |
249 | https://github.com/Thisal-D/ctkchart/assets/93121062/6d568b70-2ceb-42d0-b93c-0096f2745134
250 |
251 | ```python
252 | import customtkinter as ctk # 导入 customtkinter 库作为 ctk
253 | import ctkchart # 导入 ctkchart 模块用于创建图表
254 | import random # 导入 random 模块用于生成随机数据
255 | import threading # 导入 threading 模块用于并发运行任务
256 | import time # 导入 time 模块用于添加延迟
257 |
258 | # 创建根窗口并配置
259 | root = ctk.CTk()
260 | root.configure(fg_color=("#ffffff", "#0d1117"))
261 | root.geometry("720x430+200+200")
262 |
263 | # 创建线性图表小部件
264 | line_chart = ctkchart.CTkLineChart(
265 | master=root, # 设置根窗口为主窗口
266 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X轴的值
267 | y_axis_values=(0, 1000), # Y轴的值(范围)
268 | y_axis_label_count=10, # 设置Y轴标签数量为10
269 | )
270 |
271 | line_chart.pack(pady=15) # 将线图部件打包到根窗口中
272 |
273 | # 创建线1
274 | line1 = ctkchart.CTkLine(
275 | master=line_chart, # 设置线图的主窗口
276 | size=2, # 设置线的大小为2
277 | fill="enabled" # 启用线填充
278 | )
279 |
280 | line2 = ctkchart.CTkLine(
281 | master=line_chart, # 设置线图的主窗口
282 | color=("#5dffb6", "#5dffb6"), # 轻主题为#5dffb6,暗主题为#5dffb6
283 | size=2, # 设置线的大小为2
284 | style="dashed", # 将线的样式更改为虚线
285 | style_type=(10, 5), # 设置虚线的宽度和虚线之间的间隔
286 | )
287 |
288 | line3 = ctkchart.CTkLine(
289 | master=line_chart, # 设置线图的主窗口
290 | color=("#FFBAD2", "#FFBAD2"), # 轻主题为#FFBAD2,暗主题为#FFBAD2
291 | size=2, # 设置线的大小为2
292 | point_highlight="enabled", # 启用点高亮
293 | point_highlight_color=("#FFBAD2", "#FFBAD2"), # 设置高亮颜色
294 | )
295 |
296 | def display_data():
297 | """函数:持续在图表上显示随机数据。"""
298 | while True:
299 | random_data = [random.choice(range(0, 1000))] # 生成 0 到 1000 之间的随机数据
300 | line_chart.show_data(line=line1, data=random_data) # 显示数据在 line1 上
301 | random_data = [random.choice(range(0, 1000))] # 生成新的随机数据
302 | line_chart.show_data(line=line2, data=random_data) # 显示数据在 line2 上
303 | random_data = [random.choice(range(0, 1000))] # 生成新的随机数据
304 | line_chart.show_data(line=line3, data=random_data) # 显示数据在 line3 上
305 | time.sleep(0.5) # 暂停 0.5 秒钟再进行下一次迭代
306 |
307 | # 以独立线程运行 display_data 函数
308 | threading.Thread(target=display_data).start()
309 |
310 | # 启动主事件循环
311 | root.mainloop()
312 | ```
313 |
314 | ---
315 |
316 | - **进阶**(实际上只是添加了两个属性)
317 |
318 | https://github.com/Thisal-D/ctkchart/assets/93121062/c2838fd6-3a0f-45be-bb39-9953d007067d
319 |
320 | ```python
321 | import customtkinter as ctk # 导入 customtkinter 库作为 ctk
322 | import ctkchart # 导入 ctkchart 模块用于创建图表
323 | import random # 导入 random 模块用于生成随机数据
324 | import threading # 导入 threading 模块用于并发运行任务
325 | import time # 导入 time 模块用于添加延迟
326 |
327 | # 创建根窗口并配置
328 | root = ctk.CTk()
329 | root.configure(fg_color=("#ffffff", "#0d1117"))
330 | root.geometry("720x430+200+200")
331 |
332 | # 创建线性图表小部件
333 | line_chart = ctkchart.CTkLineChart(
334 | master=root, # 设置根窗口为主窗口
335 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X轴的值
336 | y_axis_values=(0, 1000), # Y轴的值(范围)
337 | y_axis_label_count=10, # 设置Y轴标签数量为1
338 | y_axis_section_count=10,
339 | x_axis_section_count=10,
340 | )
341 |
342 | line_chart.pack(pady=15) # 将线图部件打包到根窗口中
343 |
344 | line1 = ctkchart.CTkLine(
345 | master=line_chart, # 设置线图的主窗口
346 | color=("#5dffb6", "#5dffb6"), # 轻主题为#5dffb6,暗主题为#5dffb6
347 | size=2, # 设置线的大小为2
348 | style="dashed", # 将线的样式更改为虚线
349 | style_type=(10, 5), # 设置虚线的宽度和虚线之间的间隔
350 | )
351 |
352 | line2 = ctkchart.CTkLine(
353 | master=line_chart, # 设置线图的主窗口
354 | color=("#FFBAD2", "#FFBAD2"), # 轻主题为#FFBAD2,暗主题为#FFBAD2
355 | size=2, # 设置线的大小为2
356 | point_highlight="enabled", # 启用点高亮
357 | point_highlight_color=("#FFBAD2", "#FFBAD2"), # 设置高亮颜色
358 | )
359 |
360 | def display_data():
361 | """函数:持续在图表上显示随机数据。"""
362 | while True:
363 | random_data = [random.choice(range(0, 1000))] # 生成 0 到 1000 之间的随机数据
364 | line_chart.show_data(line=line1, data=random_data) # 显示数据在 line1 上
365 | random_data = [random.choice(range(0, 1000))] # 生成新的随机数据
366 | line_chart.show_data(line=line2, data=random_data) # 显示数据在 line2 上
367 | time.sleep(0.5) # 暂停 0.5 秒钟再进行下一次迭代
368 |
369 | # 以独立线程运行 display_data 函数
370 | threading.Thread(target=display_data).start()
371 |
372 | # 启动主事件循环
373 | root.mainloop()
374 | ```
375 |
376 | ---
377 |
378 | - #### 轻主题和暗主题
379 |
380 | **对于 ctkchart 中涉及颜色的每个参数,您可以提供以下任意一种**:
381 | - 一个字符串表示颜色。
382 | - 一个包含两个字符串的元组,第一个字符串表示轻主题颜色,第二个字符串表示暗主题颜色。
383 |
384 | https://github.com/user-attachments/assets/9fed4b83-5b03-4ea0-82a0-36029dfc93dd
385 |
386 | ---
387 |
388 | **探索可自定义的功能,如颜色、字体等,详细内容请参考文档。**
389 |
390 | #### 请参考完整文档
391 | - [**英文文档**](documentation/DOCUMENTATION_en.md)
392 | - [**中文文档**](documentation/DOCUMENTATION_zh.md)
393 |
394 | ---
395 |
396 | #### 贡献者
397 | - [ ](https://github.com/childeyouyu) [youyu](https://github.com/childeyouyu)
398 |
--------------------------------------------------------------------------------
/src/ctkchart/CTkLine.py:
--------------------------------------------------------------------------------
1 | from typing import Union, Tuple, Literal
2 | from .Validate import Validate
3 |
4 |
5 | class CTkLine:
6 | current_usable_id = 1
7 | def __init__(
8 | self,
9 | master: any = None,
10 | color: Union[Tuple[str, str], str] = ("#768df1", "#768df1"),
11 | size: int = 1,
12 | style: Literal["normal", "dashed", "dotted"] = "normal",
13 | style_type: Tuple[int, int] = (4, 4),
14 | point_highlight: Literal["enabled", "disabled"] = "disabled",
15 | point_highlight_size: int = 8,
16 | point_highlight_color: Union[Tuple[str, str], str] = ("#768df1", "#768df1"),
17 | fill: Literal["enabled", "disabled"] = "disabled",
18 | fill_color: Union[Tuple[str, str], str] = ("#bdc6ed", "#5d6db6"),
19 | *args: any
20 | ) -> None:
21 | """
22 | Initialize a CTkLine object.
23 |
24 | Args:
25 | master (any): The master object.
26 | color (Union[Tuple[str, str], str]): The color of the line.
27 | size (int): The size/thickness of the line.
28 | style (str): The style of the line (e.g., 'normal', 'dashed', 'dotted').
29 | style_type (Tuple[int, int]): The style type for dashed or dotted lines.
30 | point_highlight (str): Whether point highlighting is enabled or disabled.
31 | point_highlight_size (int): The size of points used for highlighting.
32 | point_highlight_color (Union[Tuple[str, str], str]): The color of points used for highlighting.
33 | fill (str): Whether fill for the line is enabled or disabled.
34 | fill_color (Union[Tuple[str, str], str]): The color of the fill for the line.
35 | Raises:
36 | TypeError: If any of the parameters are of an incorrect type.
37 | ValueError: If any of the parameters are invalid.
38 | """
39 | if master is None:
40 | if len(args) != 0:
41 | master = args[0]
42 | else:
43 | Validate._master_att_not_provide_for_line("master")
44 |
45 | Validate._is_valid_ctk_line_chart(master, "master")
46 | Validate._is_valid_color(color, "color")
47 | Validate._is_int(size, "size")
48 | Validate._is_valid_line_style(style, "style")
49 | Validate._is_valid_style_type(style_type, "style_type")
50 | Validate._is_valid_line_highlight(point_highlight, "point_highlight")
51 | Validate._is_int(point_highlight_size, "point_highlight_size")
52 | Validate._is_valid_color(point_highlight_color, "point_highlight_color")
53 | Validate._is_valid_line_fill(fill, "fill")
54 | Validate._is_valid_color(fill_color, "fill_color")
55 |
56 | # id (int): The id of the line. need unique
57 | self.__id = CTkLine.current_usable_id
58 | CTkLine.current_usable_id += 1
59 |
60 | self.__master = master
61 | self.__color = color
62 | self.__size = size
63 | self.__y_end = 0
64 | self.__x_end = self.__master._CTkLineChart__x_axis_point_spacing * -1
65 | self.__data = []
66 | self.__temp_data = []
67 | self.__ret_data = []
68 | self.__visibility = self.__master._CTkLineChart__visibility
69 | self.__style = style
70 | self.__style_type = style_type
71 | self.__point_highlight = point_highlight
72 | self.__point_highlight_size = point_highlight_size
73 | self.__point_highlight_color = point_highlight_color
74 | self.__fill = fill
75 | self.__fill_color = fill_color
76 |
77 | self.__master._CTkLineChart__lines.append(self)
78 |
79 | def configure(
80 | self,
81 | color: Union[Tuple[str, str], str] = None,
82 | size: int = None,
83 | style: Literal["normal", "dashed", "dotted"] = None,
84 | style_type: Tuple[int, int] = None,
85 | point_highlight: Literal["enabled", "disabled"] = None,
86 | point_highlight_size: int = None,
87 | point_highlight_color: Union[Tuple[str, str], str] = None,
88 | fill: Literal["enabled", "disabled"] = None,
89 | fill_color: Union[Tuple[str, str], str] = None
90 | ) -> None:
91 | """
92 | Configure attributes of the CTkLine object.
93 |
94 | Args:
95 | color (Union[Tuple[str, str], str]): The color of the line.
96 | size (int): The size/thickness of the line.
97 | style (str): The style of the line (e.g., 'normal', 'dashed', 'dotted').
98 | style_type (Tuple[int, int]): The style type for dashed or dotted lines.
99 | point_highlight (str): Whether point highlighting is enabled or disabled.
100 | point_highlight_size (int): The size of points used for highlighting.
101 | point_highlight_color (Union[Tuple[str, str], str]): The color of points used for highlighting.
102 | fill (str): Whether fill for the line is enabled or disabled.
103 | fill_color (Union[Tuple[str, str], str]): The color of the fill for the line.
104 |
105 | Raises:
106 | TypeError: If any of the parameters are of an incorrect type.
107 | ValueError: If any of the parameters are invalid.
108 | """
109 | changes_req = False
110 |
111 | if color is not None:
112 | Validate._is_valid_color(color, "color")
113 | self.__color = color
114 | changes_req = True
115 |
116 | if size is not None:
117 | Validate._is_int(size, "size")
118 | self.__size = size
119 | changes_req = True
120 |
121 | if style is not None:
122 | Validate._is_valid_line_style(style, "style")
123 | self.__style = style
124 | changes_req = True
125 |
126 | if style_type is not None:
127 | Validate._is_valid_style_type(style_type, "style_type")
128 | self.__style_type = style_type
129 | changes_req = True
130 |
131 | if point_highlight is not None:
132 | Validate._is_valid_line_highlight(point_highlight, "point_highlight")
133 | self.__point_highlight = point_highlight
134 | changes_req = True
135 |
136 | if point_highlight_size is not None:
137 | Validate._is_int(point_highlight_size, "point_highlight_size")
138 | self.__point_highlight_size = point_highlight_size
139 | changes_req = True
140 |
141 | if point_highlight_color is not None:
142 | Validate._is_valid_color(point_highlight_color, "point_highlight_color")
143 | self.__point_highlight_color = point_highlight_color
144 | changes_req = True
145 |
146 | if fill is not None:
147 | Validate._is_valid_line_fill(fill, "fill")
148 | self.__fill = fill
149 | changes_req = True
150 |
151 | if fill_color is not None:
152 | Validate._is_valid_color(fill_color, "fill_color")
153 | self.__fill_color = fill_color
154 | changes_req = True
155 |
156 | if changes_req:
157 | self.__master._CTkLineChart__apply_line_configuration()
158 |
159 | def get_id(self) -> int:
160 | """
161 | Get the unique identifier of the CTkLine object.
162 |
163 | Returns:
164 | int: The unique identifier of the line.
165 | """
166 | return self.__id
167 |
168 | def __reset_positions(self) -> None:
169 | """
170 | Reset the CTkLine object.
171 | """
172 | self.__y_end = 0
173 | self.__x_end = self.__master._CTkLineChart__x_axis_point_spacing * -1
174 |
175 | def __reset_data(self) -> None:
176 | self.__data = []
177 |
178 | def clear_data(self) -> None:
179 | """
180 | Clears the chart data, ensuring that only the relevant visible data is retained.
181 |
182 | This method works by checking the maximum number of data points across all lines in the chart
183 | and the maximum number of visible data points. If the chart contains more data points than
184 | the visible limit, the data is cropped so that only the most recent data points (up to the
185 | visible limit) are kept. If the chart is already within the visible limit, the data is not altered.
186 |
187 | The data is trimmed from the beginning of the dataset, and the most recent points are kept.
188 |
189 | This ensures that the chart does not display more data than the allowed visible limit,
190 | optimizing performance and display consistency.
191 |
192 | Attributes:
193 | self.__data: The internal list that holds all the data for the lines on the chart.
194 |
195 | Returns:
196 | None: This method modifies the internal state of the data but does not return any value.
197 | """
198 | maximum_data = self.__master._CTkLineChart__get_max_data_length_across_lines()
199 | max_visible_points = self.__master._CTkLineChart__get_max_visible_data_points()
200 |
201 | if maximum_data > max_visible_points:
202 | self.__data = self.__data[maximum_data - max_visible_points::]
203 |
204 | def get_data(self, start: int = None, end: int = None, step: int = None) -> Tuple[int | float]:
205 | """
206 | Retrieve data points from the specified range and step.
207 |
208 | Args:
209 | start (int, optional): The starting index for slicing the data. Defaults to None.
210 | end (int, optional): The ending index for slicing the data. Defaults to None.
211 | step (int, optional): The step size for slicing the data. Defaults to None.
212 |
213 | Returns:
214 | Tuple[int | float]: A tuple of data points from the specified range and step.
215 | """
216 | return tuple(self.__data[start: end: step])
217 |
218 | def get_current_visible_data(self) -> Tuple[int | float]:
219 | """
220 | Retrieve the currently visible data points.
221 |
222 | Determines visible data points based on the maximum data length across all lines
223 | and the maximum number of visible points.
224 |
225 | Returns:
226 | Tuple[int | float]: A tuple of currently visible data points.
227 | If no data is visible, an empty tuple is returned.
228 | """
229 | maximum_data = self.__master._CTkLineChart__get_max_data_length_across_lines()
230 | max_visible_points = self.__master._CTkLineChart__get_max_visible_data_points()
231 |
232 | data = ()
233 | if maximum_data > max_visible_points:
234 | data = tuple(self.__data[maximum_data - max_visible_points::])
235 | else:
236 | data = ()
237 | return data
238 |
239 | def get_x_axis_visible_point_count(self) -> int:
240 | """
241 | Get the maximum number of data points that can be visible along the X-axis.
242 |
243 | Returns:
244 | int: The maximum number of visible data points on the X-axis.
245 | """
246 | return self.__master.get_x_axis_visible_point_count()
247 |
248 | def reset(self) -> None:
249 | """
250 | Reset the line.
251 | """
252 | self.__reset_positions()
253 | self.__reset_data()
254 | self.__master._CTkLineChart__apply_line_configuration()
255 |
256 | def set_visible(self, state: bool) -> None:
257 | """
258 | Set the visibility of the line.
259 |
260 | Args:
261 | state (bool): True if the line should be visible, False otherwise.
262 |
263 | Raises:
264 | TypeError: If the state is not a boolean.
265 | """
266 | Validate._is_bool(state, "state")
267 | if self.__visibility != state:
268 | self.__visibility = state
269 | self.__master._CTkLineChart__apply_line_configuration()
270 |
271 | def cget(
272 | self,
273 | attribute_name: Literal[
274 | "master", "color", "size", "style", "style_type", "point_highlight",
275 | "point_highlight_size", "point_highlight_color", "fill", "fill_color",
276 | "__all__"
277 | ] = "__all__"
278 | ) -> any:
279 | """
280 | Get the value of a CTkLine attribute.
281 |
282 | Args:
283 | attribute_name (str): Name of the attribute.
284 |
285 | Returns:
286 | any: Value of the attribute.
287 |
288 | Raises:
289 | ValueError: If the attribute name is invalid.
290 | """
291 | if attribute_name == "master":
292 | return self.__master
293 | elif attribute_name == "color":
294 | return self.__color
295 | elif attribute_name == "size":
296 | return self.__size
297 | elif attribute_name == "style":
298 | return self.__style
299 | elif attribute_name == "style_type":
300 | return self.__style_type
301 | elif attribute_name == "point_highlight":
302 | return self.__point_highlight
303 | elif attribute_name == "point_highlight_size":
304 | return self.__point_highlight_size
305 | elif attribute_name == "point_highlight_color":
306 | return self.__point_highlight_color
307 | elif attribute_name == "fill":
308 | return self.__fill
309 | elif attribute_name == "fill_color":
310 | return self.__fill_color
311 | elif attribute_name == "__all__":
312 | return {
313 | "master": self.__master,
314 | "color": self.__color,
315 | "size": self.__size,
316 | "style": self.__style,
317 | "style_type": self.__style_type,
318 | "point_highlight": self.__point_highlight,
319 | "point_highlight_size": self.__point_highlight_size,
320 | "point_highlight_color": self.__point_highlight_color,
321 | "fill": self.__fill,
322 | "fill_color": self.__fill_color
323 | }
324 | else:
325 | Validate._invalid_cget(attribute_name)
326 |
327 | def get_visibility(self) -> bool:
328 | """
329 | Get the visibility of the line.
330 |
331 | Returns:
332 | bool: True if the line is visible, False otherwise.
333 | """
334 | return self.__visibility
335 |
336 | def __del__(self) -> None:
337 | """Destructor method to delete instance attributes."""
338 | del self.__id
339 | del self.__master
340 | del self.__color
341 | del self.__size
342 | del self.__y_end
343 | del self.__x_end
344 | del self.__data
345 | del self.__temp_data
346 | del self.__ret_data
347 | del self.__visibility
348 | del self.__style
349 | del self.__style_type
350 | del self.__point_highlight
351 | del self.__point_highlight_size
352 | del self.__point_highlight_color
353 | del self.__fill
354 | del self.__fill_color
355 |
356 | def destroy(self) -> None:
357 | """
358 | Removes the instance from its master's line chart and
359 | applies the updated line configuration. Calls the destructor
360 | to clean up resources.
361 | """
362 | try:
363 | self.__master._CTkLineChart__lines.remove(self)
364 | self.__master._CTkLineChart__apply_line_configuration()
365 | except ValueError:
366 | pass # In case the line is not in the list
367 | finally:
368 | self.__del__()
369 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](README_zh.md)
2 |
3 |
4 |
5 | [](https://snyk.io/advisor/python/ctkchart)
6 |
7 | # ctkchart
8 |
9 | [](https://pypi.org/project/ctkchart/)
10 |
11 | [](https://pepy.tech/project/ctkchart)  [](https://pepy.tech/project/ctkchart) [](https://pepy.tech/project/ctkchart)
12 |
13 |
14 | 
15 | 
16 |
17 |
18 |
19 |
20 | **ctkchart is a Python library for creating live updating line charts in customtkinter. **
21 |
22 | ---
23 |
24 | ### Features
25 |
26 | - **Live Update**: Display live data with line charts.
27 | - **Multiple Lines**: Support for plotting multiple lines on the same chart for easy comparison.
28 | - **Color Customization**: Customize colors to match your application's design or data representation.
29 | - **Dynamic Color Change**: Dynamic Color Change for Dark & Light.
30 | - **Font Customization**: Adjust fonts for text elements to enhance readability.
31 | - **Dimension Customization**: Customize chart dimensions to fit various display sizes and layouts.
32 |
33 | [**Check out what's new | Changes**](CHANGES_en.md)
34 |
35 | ---
36 |
37 | ### Importing & Installation
38 | * **Installation**
39 | ```
40 | pip install ctkchart
41 | ```
42 |
43 | * **Importing**
44 | ``` python
45 | import ctkchart
46 | ```
47 | ---
48 |
49 |
50 | ### Simple Guide
51 | - **import package**
52 | ``` python
53 | import tkchart
54 | ```
55 |
56 | - **Create Line Chart and place the chart**
57 | ``` python
58 | chart = ctkchart.CTkLineChart(
59 | master=root,
60 | x_axis_values=("a", "b", "c", "d", "e", "f"),
61 | y_axis_values=(100, 900)
62 | )
63 | chart.place(x=10, y=10)
64 | ```
65 |
66 | - **Create Line**
67 | ``` python
68 | line = ctkchart.CTkLine(master=chart)
69 | ```
70 |
71 | - **Display Data**
72 | display data using a loop
73 | ``` python
74 | def loop():
75 | while True:
76 | random_data = random.choice(range(100, 900))
77 | chart.show_data(line=line, data=[random_data])
78 | time.sleep(1)
79 |
80 | #call the loop as thead
81 | theading.Thread(target=loop).start()
82 | ```
83 |
84 | ---
85 |
86 | ### Links
87 |
88 | - **Documentation :** [Documents](documentation)
89 | - [English doc.](documentation/DOCUMENTATION_en.md)
90 | - [Chinese doc.](documentation/DOCUMENTATION_zh.md)
91 | - **Python official :** [ctkchart](https://pypi.org/project/ctkchart/)
92 |
93 | ---
94 |
95 | ### What You Can Accomplish
96 |
97 | - **Simple**
98 |
99 | https://github.com/Thisal-D/ctkchart/assets/93121062/6f1e844f-d51c-467a-a3dc-ee03fea78fc9
100 |
101 | ``` python
102 | import customtkinter as ctk # Importing the customtkinter library as ctk
103 | import ctkchart # Importing the ctkchart module for chart creation
104 | import random # Importing the random module for generating random data
105 | import threading # Importing the threading module for running tasks concurrently
106 | import time # Importing the time module for adding delays
107 |
108 | # Create the root window and configure
109 | root = ctk.CTk()
110 | root.configure(fg_color="#0d1117")
111 | root.geometry("720x430+200+200")
112 |
113 | # Create a line chart widget
114 | line_chart = ctkchart.CTkLineChart(
115 | master=root, # Set the master as the root window
116 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X-axis values
117 | y_axis_values=(0, 1000) # Y-axis values (range)
118 | )
119 |
120 | line_chart.pack(pady=15) # Pack the line chart widget into the root
121 |
122 | # Create a line for the line chart
123 | line = ctkchart.CTkLine(master=line_chart) # Set the master as the line chart
124 |
125 | def display_data():
126 | """Function to continuously display random data on the line chart."""
127 | while True:
128 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
129 | line_chart.show_data(line=line, data=random_data) # Display the random data on the line chart
130 | time.sleep(0.5) # Pause for 0.5 seconds before the next iteration
131 |
132 | # Call the display_data function as a separate thread
133 | threading.Thread(target=display_data).start()
134 |
135 | # Start the main event loop
136 | root.mainloop()
137 | ```
138 | ---
139 |
140 | - **Simple style**
141 |
142 | https://github.com/Thisal-D/ctkchart/assets/93121062/afe56452-68c3-44f0-9c67-2ab6f6910f6e
143 |
144 | ``` python
145 | import customtkinter as ctk # Importing the customtkinter library as ctk
146 | import ctkchart # Importing the ctkchart module for chart creation
147 | import random # Importing the random module for generating random data
148 | import threading # Importing the threading module for running tasks concurrently
149 | import time # Importing the time module for adding delays
150 |
151 | # Create the root window and configure
152 | root = ctk.CTk()
153 | root.configure(fg_color="#0d1117")
154 | root.geometry("720x430+200+200")
155 |
156 | # Create a line chart widget
157 | line_chart = ctkchart.CTkLineChart(
158 | master=root, # Set the master as the root window
159 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X-axis values
160 | y_axis_values=(0, 1000), # Y-axis values (range)
161 | y_axis_label_count=10, # set y axis labels count to 10
162 | )
163 |
164 | line_chart.pack(pady=15) # Pack the line chart widget into the root
165 |
166 | # Create a line for the line chart
167 | line = ctkchart.CTkLine(
168 | master=line_chart, # Set the master as the line chart
169 | size=2, # Set the line size to 2
170 | fill="enabled" # enable line fill
171 | )
172 |
173 | def display_data():
174 | """Function to continuously display random data on the line chart."""
175 | while True:
176 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
177 | line_chart.show_data(line=line, data=random_data) # Display the random data on the line chart
178 | time.sleep(0.5) # Pause for 0.5 seconds before the next iteration
179 |
180 | # Call the display_data function as a separate thread
181 | threading.Thread(target=display_data).start()
182 |
183 | # Start the main event loop
184 | root.mainloop()
185 | ```
186 | ---
187 |
188 | - **2 lines with different line styles**
189 |
190 | https://github.com/Thisal-D/ctkchart/assets/93121062/9bc35a39-a8ca-4942-9fc7-a1c89d1bd1bc
191 |
192 | ``` python
193 | import customtkinter as ctk # Importing the customtkinter library as ctk
194 | import ctkchart # Importing the ctkchart module for chart creation
195 | import random # Importing the random module for generating random data
196 | import threading # Importing the threading module for running tasks concurrently
197 | import time # Importing the time module for adding delays
198 |
199 | # Create the root window and configure
200 | root = ctk.CTk()
201 | root.configure(fg_color=("#ffffff", "#0d1117"))
202 | root.geometry("720x430+200+200")
203 |
204 | # Create a line chart widget
205 | line_chart = ctkchart.CTkLineChart(
206 | master=root, # Set the master as the root window
207 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X-axis values
208 | y_axis_values=(0, 1000), # Y-axis values (range)
209 | y_axis_label_count=10, # set y axis labels count to 10
210 | )
211 |
212 | line_chart.pack(pady=15) # Pack the line chart widget into the root
213 |
214 | line1 = ctkchart.CTkLine(
215 | master=line_chart, # Set the master as the line chart
216 | color=("#5dffb6","#5dffb6"), # index 0 for light and 1 for dark theme
217 | size=2, # Set the line size to 2
218 | style="dashed", # style change to dashed
219 | style_type=(10, 5), #index 0 for dash width and 1 for space between dashes
220 | )
221 |
222 | line2 = ctkchart.CTkLine(
223 | master=line_chart, # Set the master as the line chart
224 | color=("#FFBAD2", "#FFBAD2"), # index 0 for light and 1 for dark theme
225 | size=2, # Set the line size to 2
226 | point_highlight="enabled", # enable point highlight
227 | point_highlight_color=("#FFBAD2", "#FFBAD2"), # enable point highlight
228 | )
229 |
230 | def display_data():
231 | """Function to continuously display random data on the line chart."""
232 | while True:
233 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
234 | line_chart.show_data(line=line1, data=random_data) # Display the random data on the line 1 on chart
235 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
236 | line_chart.show_data(line=line2, data=random_data) # Display the random data on the line 2 on chart
237 | time.sleep(0.5) # Pause for 0.5 seconds before the next iteration
238 |
239 | # Call the display_data function as a separate thread
240 | threading.Thread(target=display_data).start()
241 |
242 | # Start the main event loop
243 | root.mainloop()
244 | ```
245 | ---
246 |
247 | - **3 lines with different line styles**
248 |
249 | https://github.com/Thisal-D/ctkchart/assets/93121062/6d568b70-2ceb-42d0-b93c-0096f2745134
250 |
251 | ``` python
252 | import customtkinter as ctk # Importing the customtkinter library as ctk
253 | import ctkchart # Importing the ctkchart module for chart creation
254 | import random # Importing the random module for generating random data
255 | import threading # Importing the threading module for running tasks concurrently
256 | import time # Importing the time module for adding delays
257 |
258 | # Create the root window and configure
259 | root = ctk.CTk()
260 | root.configure(fg_color=("#ffffff", "#0d1117"))
261 | root.geometry("720x430+200+200")
262 |
263 | # Create a line chart widget
264 | line_chart = ctkchart.CTkLineChart(
265 | master=root, # Set the master as the root window
266 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X-axis values
267 | y_axis_values=(0, 1000), # Y-axis values (range)
268 | y_axis_label_count=10, # set y axis labels count to 10
269 | )
270 |
271 | line_chart.pack(pady=15) # Pack the line chart widget into the root
272 |
273 | # Create a line 1 for the line chart
274 | line1 = ctkchart.CTkLine(
275 | master=line_chart, # Set the master as the line chart
276 | size=2, # Set the line size to 2
277 | fill="enabled" # enable line fill
278 | )
279 |
280 | line2 = ctkchart.CTkLine(
281 | master=line_chart, # Set the master as the line chart
282 | color=("#5dffb6","#5dffb6"), # index 0 for light and 1 for dark theme
283 | size=2, # Set the line size to 2
284 | style="dashed", # style change to dashed
285 | style_type=(10, 5), #index 0 for dash width and 1 for space between dashes
286 | )
287 |
288 | line3 = ctkchart.CTkLine(
289 | master=line_chart, # Set the master as the line chart
290 | color=("#FFBAD2", "#FFBAD2"), # index 0 for light and 1 for dark theme
291 | size=2, # Set the line size to 2
292 | point_highlight="enabled", # enable point highlight
293 | point_highlight_color=("#FFBAD2", "#FFBAD2"), # enable point highlight
294 | )
295 |
296 | def display_data():
297 | """Function to continuously display random data on the line chart."""
298 | while True:
299 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
300 | line_chart.show_data(line=line1, data=random_data) # Display the random data on the line 1 on chart
301 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
302 | line_chart.show_data(line=line2, data=random_data) # Display the random data on the line 2 on chart
303 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
304 | line_chart.show_data(line=line3, data=random_data) # Display the random data on the line 3 on chart
305 | time.sleep(0.5) # Pause for 0.5 seconds before the next iteration
306 |
307 | # Call the display_data function as a separate thread
308 | threading.Thread(target=display_data).start()
309 |
310 | # Start the main event loop
311 | root.mainloop()
312 | ```
313 | ---
314 |
315 | - **Advance** (Actually not, Just Two More Attributes Added)
316 |
317 | https://github.com/Thisal-D/ctkchart/assets/93121062/c2838fd6-3a0f-45be-bb39-9953d007067d
318 |
319 | ``` python
320 | import customtkinter as ctk # Importing the customtkinter library as ctk
321 | import ctkchart # Importing the ctkchart module for chart creation
322 | import random # Importing the random module for generating random data
323 | import threading # Importing the threading module for running tasks concurrently
324 | import time # Importing the time module for adding delays
325 |
326 | # Create the root window and configure
327 | root = ctk.CTk()
328 | root.configure(fg_color=("#ffffff", "#0d1117"))
329 | root.geometry("720x430+200+200")
330 |
331 | # Create a line chart widget
332 | line_chart = ctkchart.CTkLineChart(
333 | master=root, # Set the master as the root window
334 | x_axis_values=("01-01", "01-02", "01-03", "01-04", "01-05", "01-06", "01-07", "01-08", "01-09", "01-10"), # X-axis values
335 | y_axis_values=(0, 1000), # Y-axis values (range)
336 | y_axis_label_count=10, # set y axis labels count to 1
337 | y_axis_section_count=10,
338 | x_axis_section_count=10,
339 | )
340 |
341 | line_chart.pack(pady=15) # Pack the line chart widget into the root
342 |
343 | line1 = ctkchart.CTkLine(
344 | master=line_chart, # Set the master as the line chart
345 | color=("#5dffb6","#5dffb6"), # index 0 for light and 1 for dark theme
346 | size=2, # Set the line size to 2
347 | style="dashed", # style change to dashed
348 | style_type=(10, 5), #index 0 for dash width and 1 for space between dashes
349 | )
350 |
351 | line2 = ctkchart.CTkLine(
352 | master=line_chart, # Set the master as the line chart
353 | color=("#FFBAD2", "#FFBAD2"), # index 0 for light and 1 for dark theme
354 | size=2, # Set the line size to 2
355 | point_highlight="enabled", # enable point highlight
356 | point_highlight_color=("#FFBAD2", "#FFBAD2"), # enable point highlight
357 | )
358 |
359 | def display_data():
360 | """Function to continuously display random data on the line chart."""
361 | while True:
362 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
363 | line_chart.show_data(line=line1, data=random_data) # Display the random data on the line 1 on chart
364 | random_data = [random.choice(range(0, 1000))] # Generate random data between 0 and 1000
365 | line_chart.show_data(line=line2, data=random_data) # Display the random data on the line 2 on chart
366 | time.sleep(0.5) # Pause for 0.5 seconds before the next iteration
367 |
368 | # Call the display_data function as a separate thread
369 | threading.Thread(target=display_data).start()
370 |
371 | # Start the main event loop
372 | root.mainloop()
373 | ```
374 | ---
375 |
376 | - #### Light and Dark theme
377 |
378 | **For every parameter that involves color in ctkchart, you can provide either**:
379 | - A single string representing the color.
380 | - A tuple of two strings where the first string represents the color for the light theme and the second string represents the color for the dark theme.
381 |
382 | https://github.com/user-attachments/assets/9fed4b83-5b03-4ea0-82a0-36029dfc93dd
383 |
384 | ---
385 |
386 | **Explore customizable features such as colors, fonts, and more in the documentation.**
387 |
388 | #### Please refer to the full documentation
389 | - [**English doc.**](documentation/DOCUMENTATION_en.md)
390 | - [**Chinese doc.**](documentation/DOCUMENTATION_zh.md)
391 |
392 | ---
393 |
394 | #### Contributors
395 | - [ ](https://github.com/childeyouyu) [youyu](https://github.com/childeyouyu)
396 |
--------------------------------------------------------------------------------
/documentation/DOCUMENTATION_zh.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [](DOCUMENTATION_en.md)
4 |
5 | ---
6 |
7 | **如何使用** | **例子** | **参数说明** | **查看新功能**
8 |
9 |
10 |
11 | ### 安装和使用
12 | * 安装
13 | ```
14 | pip install ctkchart
15 | ```
16 |
17 | * 使用
18 | ``` python
19 | import ctkchart
20 | ```
21 | ---
22 |
23 |
24 |
25 | ### 参数概述
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ---
35 |
36 |
37 |
38 |
39 |
40 | ### 要使用 ctkchart 显示数据,您需要执行以下三步:
41 | 1.
**创建折线图**
42 | 2.
**创建一条线**
43 | 3.
**数据显示**
44 |
45 | ---
46 |
47 |
48 |
49 | ## 1 . 创建折线图
50 |
**创建一条线** |
**数据显示**
51 |
52 | ``` python
53 | linechart = ctkchart.CTkLineChart()
54 | ```
55 |
56 | ### 参数
57 |
58 | | 参数 | 必备参数 / 可选参数 | 描述 | 数据类型 | 示例值 |
59 | |-------------------------------------------------|-------------|--------------------|---------------------------------|----------------------------------------|
60 | | master | ***必须*** | 折线图主体 | ``widget`` | widget |
61 | | [y_axis_values](#x_y_axis_values) | ***必须*** | y 轴的最小值和最大值 | ``tuple[int \| float], ...`` | (-1000, 1000), ... |
62 | | [x_axis_values](#x_y_axis_values) | ***必须*** | x 轴的值 | ``tuple[any, ...]`` | (1, 2, 3, 4, 5), ... |
63 | | width | ***可选*** | 折线图的宽度 | ``int`` | 300, ... |
64 | | height | ***可选*** | 折线图的高度 | ``int`` | 100, ... |
65 | | [axis_size](#parameter_img) | ***可选*** | 坐标轴宽度 | ``int`` | 1<= |
66 | | [axis_color](#parameter_img) | ***可选*** | 坐标轴轴颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
67 | | [bg_color](#parameter_img) | ***可选*** | 折线图的背景色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
68 | | [fg_color](#parameter_img) | ***可选*** | 折线图的前景色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
69 | | [data_font_style](#x_y_data) | ***可选*** | 坐标轴名称的字体样式 | ``tuple[str, int, str]`` | ("arial", 9, "bold"), ... |
70 | | [axis_font_style](#x_y_font_style) | ***可选*** | 坐标轴文字的字体样式 | ``tuple[str, int, str]`` | ("arial", 8, "normal"), ... |
71 | | [x_axis_data](#x_y_data) | ***可选*** | x_data 的值(x 坐标轴名称) | ``str`` | "X", ... |
72 | | [y_axis_data](#x_y_data) | ***可选*** | y_data 的值(y 坐标轴名称) | ``any`` | "Y", ... |
73 | | [x_axis_data_font_color](#x_y_data) | ***可选*** | x_data 的字体颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), "#707070", ... |
74 | | [y_axis_data_font_color](#x_y_data) | ***可选*** | y_data 的字体颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), "#707070", ... |
75 | | [x_axis_data_position](#data_position) | ***可选*** | x_data 的排布方式 | ``str`` | "top" |
76 | | [y_axis_data_position](#data_position) | ***可选*** | y_data 的排布方式 | ``str`` | "top" |
77 | | [x_axis_section_count](#x_y_section) | ***可选*** | x 轴上的网格线数 | ``int`` | 0<= |
78 | | [y_axis_section_count](#x_y_section) | ***可选*** | y 轴上的网格线数 | ``int`` | 0<= |
79 | | [x_axis_label_count](#x_y_label_count) | ***可选*** | x 轴标签数量 | ``int`` | 0<= |
80 | | [y_axis_label_count](#x_y_label_count) | ***可选*** | y 轴标签数量 | ``int`` | 1<= |
81 | | [x_axis_font_color](#x_y_font_style) | ***可选*** | x 轴标签的字体颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), "#606060", ... |
82 | | [y_axis_font_color](#x_y_font_style) | ***可选*** | y 轴标签的字体颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), "#606060", ... |
83 | | [x_axis_section_style](#x_y_section_style) | ***可选*** | x 轴上的网格线样式 | ``str`` | "normal" |
84 | | [y_axis_section_style](#x_y_section_style) | ***可选*** | y 轴上的网格线样式 | ``str`` | "normal" |
85 | | [x_axis_section_style_type](#x_y_section_style) | ***可选*** | x 轴上网格线的实线与空白的尺寸 | ``tuple[int, int]`` | (100, 50) , (50,50), ... |
86 | | [y_axis_section_style_type](#x_y_section_style) | ***可选*** | y 轴上网格线的实线与空白的尺寸 | ``tuple[int, int]`` | (100, 50) |
87 | | [x_axis_section_color](#x_y_section) | ***可选*** | x 轴上网格线的颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), "#2C2C2C", ... |
88 | | [y_axis_section_color](#x_y_section) | ***可选*** | y 轴上网格线的颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), "#2C2C2C" |
89 | | [y_axis_precision](#y_precision) | ***可选*** | y 轴值的精度 | ``int`` | 0<= |
90 | | [x_axis_display_values_indices](#indices_view) | ***可选*** | 显示在 x 轴上的坐标值的索引 | ``tuple[int, ...]`` | (0, 1, 2, 3, 4, 5), ... |
91 | | [x_axis_point_spacing](#x_axis_point_spacing) | ***可选*** | 线条宽度 | ``int`` \| ``str`` "auto" | "auto"
1<= |
92 | | [x_space](#parameter_img) | ***可选*** | x 轴和图表区域之间的空间 | ``int`` | 0<= |
93 | | [y_space](#parameter_img) | ***可选*** | y 轴和图表区域之间的空间 | ``int`` | 0<= |
94 | | pointer_state | ***可选*** | 鼠标状态 | ``str`` ("enabled", "disabled") | "disabled" |
95 | | pointing_callback_function | ***可选*** | 鼠标的回调函数 | ``callable`` | function(*args)
function(x, y) |
96 | | pointer_color | ***可选*** | 鼠标颜色 | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), "#606060", ... |
97 | | pointing_values_precision | ***可选*** | 指向值的精度 | ``int`` | 0<= |
98 | | pointer_lock | ***可选*** | 鼠标锁状态 | ``str`` ("enabled", "disabled") | "enabled" |
99 | | pointer_size | ***可选*** | 鼠标显示线的宽度 | ``int`` | 1<= |
100 |
101 | ---
102 |
103 | ### 方法
104 |
105 | | 方法 | 描述 | 支持的参数 / 必须的参数 | 返回类型 |
106 | |----------------------------|---------------------|----------------------------------------------------------------------------------------------------------------------------------|----------|
107 | | configure | 更改 LineChart(折线图)属性 | 所有属性,除了 master | ``None`` |
108 | | [show_data](#display-data) | 显示数据 | data: ``list``
line: ``ctkchart.CTkLine`` | ``None`` |
109 | | place | 放置 (place) 折线图 | x: ``int``
y: ``int``
rely: ``float or int``
relx: ``float or int``
anchor: ``str`` | ``None`` |
110 | | pack | 放置 (pack) 折线图 | pady: ``int``
padx: ``int``
before: ``widget``
after: ``widget``
side: ``str``
anchor: ``str`` | ``None`` |
111 | | grid | 放置 (grid) 折线图 | column: ``int``
columnspan: ``int``
padx: ``int``
pady: ``int``
row: ``int``
rowspan: ``int``
sticky: ``str`` | ``None`` |
112 | | place_forget | Place 忘编号 | - | ``None`` |
113 | | pack_forget | Pack 忘编号 | - | ``None`` |
114 | | grid_forget | Grid 忘编号 | - | ``None`` |
115 | | set_lines_visibility | 更改所有线条的可见性 | state: ``bool`` | ``None`` |
116 | | set_line_visibility | 更改特定行的可见性 | line: ``ctkchart.CTkLine``
state: ``bool`` | ``None`` |
117 | | get_line_visibility | 获取特定生产线的可见性 | line: ``ctkchart.CTkLine`` | ``bool`` |
118 | | reset | 重置折线图 | - | ``None`` |
119 | | cget | 获取指定参数的值。 | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
120 | | place_info | 获取地点信息 | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
121 | | pack_info | 获取有关包装的信息 | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
122 | | grid_info | 获取网格信息 | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
123 | | get_line_area | 获取特定线的面积 | line: `ctkchart.CTkLine` | `float` |
124 | | get_lines_area | 获取所有线的面积 | - | `float` |
125 | | clear_data | 清除图表中所有线的数据,确保只保留最新的可见数据点。如果数据点总数超过最大可见点,则会从每条线的数据中移除旧数据。此方法确保图表仅显示基于最大可见范围的相关数据部分。 | - | ``None`` |
126 | | destroy | 销毁图表 | - | ``None`` |
127 | | get_lines_data | 获取指定范围内所有线条的数据点,可以选择步长值。 | start: `int`
end: `int`
step: `int` | `Dict[ctkchart.CTkLine, Tuple[int]]` |
128 | | get_line_data | 获取指定范围和步长值下某一条线的数据点。 | line: `ctkchart.CTkLine`
start: `int`
end: `int`
step: `int` | `Tuple[int \| float]` |
129 | | get_x_axis_visible_point_count | 获取X轴上可见数据点的最大数量。 | - | `int` |
130 | | get_lines_visible_data | 获取所有线条当前可见的数据点,基于最大数据长度和可见点数。 | - | `Dict[ctkchart.CTkLine, Tuple[int \| float]]` |
131 | | get_line_visible_data | 获取某一条线当前可见的数据点。 | line: `ctkchart.CTkLine` | `Tuple[int \| float]` |
132 |
133 |
134 |
135 |
136 |
137 | ---
138 |
139 | ## 2 . 创建一条线
140 |
141 |
**创建折线图** |
**数据显示**
142 |
143 | ``` python
144 | line = ctkchart.CTkLine()
145 | ```
146 |
147 | ### 参数
148 |
149 | | 参数名称 | 必备参数 / 可选参数 | 描述 | 数据类型 | 示例值 |
150 | |-------------------------------------------|-------------|------------------|----------------------------------------|---------------|
151 | | master | 必须 | Master | ``ctkchart.CTkLine`` | LineChart obj |
152 | | [color](#line_color_size) | 可选 | 折线的颜色 | ``str`` | "#768df1" |
153 | | [size](#line_color_size) | 可选 | Size of the line | ``int`` | 1<= |
154 | | [style](#line_style) | 可选 | 折线风格(直线、虚线、点线) | ``str`` ("normal", "dashed", "dotted") | "normal" |
155 | | [style_type](#line_style_type) | 可选 | 实线与虚线的尺寸 | ``tuple[int, int]`` | (10, 5),... |
156 | | [point_highlight](#point_highlight) | 可选 | 端点高亮状态 | ``str`` ("enabled", "disabled") | "disabled" |
157 | | [point_highlight_size](#point_highlight) | 可选 | 高亮点的大小 | ``int`` | 1<= |
158 | | [point_highlight_color](#point_highlight) | 可选 | 高亮点的颜色 | ``str`` | "#768df1" |
159 | | [fill](#fill) | 可选 | 是否启用填充 | ``str`` ("enabled", "disabled") | "disabled" |
160 | | [fill_color](#fill) | 可选 | 填充部分的颜色 | ``str`` | "#5d6db6" |
161 |
162 | ---
163 |
164 | ### 方法
165 |
166 | | 方法 | 描述 | 支持的参数 | 返回类型 |
167 | |----------------|----------|------------------------------------------|----------|
168 | | configure | 更改折线图属性 | 所有属性,除了 master | ``None`` |
169 | | cget | 获取指定参数的值 | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
170 | | reset | 重置线对象 | - | ``None`` |
171 | | set_visible | 改变线条的可见度 | state: ``bool`` | ``None`` |
172 | | get_visibility | 获得线路的可见度 | - | ``bool`` |
173 | | clear_data | 清除特定线的数据,确保只保留最新的可见数据点。如果线的数据超过最大可见点,则会修剪旧数据。此方法允许每条线独立清除其数据,确保它始终保持在可见范围内。 | - | ``None`` |
174 | | destroy | 破坏线 | - | ``None`` |
175 | | get_data | 获取指定范围的数据点,可以选择步长值。如果没有提供参数,将返回所有可用数据。 | start: `int`
end: `int`
step: `int` | `Tuple[int \| float]` |
176 | | get_current_visible_data | 根据所有线条的最大数据长度和最大可见点数,返回当前可见的数据点。 | - | `Tuple[int \| float]` |
177 | | get_x_axis_visible_point_count | 获取X轴上可见数据点的最大数量。 | - | `int` |
178 |
179 |
180 |
181 |
182 |
183 | ---
184 |
185 |
186 |
187 | ## 3 . 数据显示
188 |
189 |
**创建折线图** |
**创建一条折线**
190 |
191 |
192 | ``` python
193 | import tkinter as tk
194 | import ctkchart
195 | import random
196 |
197 | ## root
198 | root = tk.Tk()
199 | root.configure(bg="#151515")
200 |
201 | ## 创建折线图
202 | chart = ctkchart.CTkLineChart(
203 | master=root,
204 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
205 | y_axis_values = (-100,100)
206 | )
207 | chart.pack()
208 |
209 | ## 创建一条折线
210 | line = ctkchart.CTkLine(master=chart)
211 |
212 | data = [x for x in range(-100,101)] #values -100 to 100
213 | ## 显示数据(随机)
214 | def loop():
215 | chart.show_data(line=line, data=random.choices(data, k=1))
216 | root.after(500, loop)
217 | loop()
218 |
219 | root.mainloop()
220 | ```
221 |
222 |
223 |
224 | https://github.com/Thisal-D/tkchart/assets/93121062/64440c23-63e6-4093-b027-21b00a6f5518
225 |
226 | ---
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
**返回顶部** |
**使用指南** |
**例子** |
**查看新功能**
236 |
237 | ## 参数说明
238 |
239 |
240 |
241 | ### CTkLineChart
242 |
243 | - #### y_axis_values
244 | y_axis_values 是一个包含两个数值的元组。第一个值(索引 0)表示 y 轴的起始值,第二个值(索引 1)表示 y 轴的结束值。该元组定义了折线图上沿 y 轴显示的值的范围。
245 |
246 | - #### x_axis_values
247 | x_axis_values 是可以包含任何数据类型的值的集合。这些值被分配给 x 轴,从索引 0 开始一直到 x_axis_values 元组的最后一个索引。元组中的每个值对应于折线图中 x 轴上的一个点。
248 |
249 |
250 |
251 |
252 |
253 |
254 | ``` python
255 | chart = ctkchart.CTkLineChart(
256 | master=any_widget,
257 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
258 | y_axis_values=(-100, 100)
259 | )
260 | ```
261 |
262 | ---
263 |
264 |
265 |
266 |
267 |
268 | - #### x_axis_data
269 | 指折线图 x 轴上显示的值类型。
270 | **注意:"X"为默认值。**
271 |
272 | - #### y_axis_data
273 | 指折线图 y 轴上显示的值类型。
274 | **注意:"Y" 是默认值。**
275 |
276 | - #### x_axis_data_font_color
277 | 指应用于表示折线图 x_axis_data 的标签的字体颜色。
278 |
279 | - #### y_axis_data_font_color
280 | 指应用于表示折线图 y_axis_data 的标签的字体颜色。
281 |
282 | - #### data_font_style
283 | 指应用于代表折线图 x_axis_data 和 y_axis_data 的标签的字体样式。
284 |
285 |
286 |
287 |
288 |
289 |
290 | ``` python
291 | chart = ctkchart.CTkLineChart(
292 | master=any_widget,
293 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
294 | y_axis_values=(-100, 100),
295 | y_axis_data="Y data" ,
296 | x_axis_data="X data",
297 | x_axis_data_font_color="#ff0000",
298 | y_axis_data_font_color="#00ff00",
299 | data_font_style=("arial", 15, "underline")
300 | )
301 | ```
302 |
303 | ---
304 |
305 |
306 |
307 |
308 |
309 | - #### x_axis_label_count
310 | 当您有一组 x_value(例如从 2018 年到 2025 年)时,通常会显示所有这些标签。但有时为了更清晰起见,您可能只想显示其中的几个。
311 | 例如,如果您将 x_axis_label_count 设置为 4,则意味着您只想显示 4 个标签,而不是全部 8 个。因此,折线图将自动跳过一些标签以适合您指定的数量。
312 | **注意:len(
x_axis_values ) 是默认值。**
313 | 换句话说,调整 x_axis_label_count 可以让您控制 x 轴上显示的标签数量,使您的可视化更清晰、更易于理解。
314 |
315 | -**如果有 9 个标签,您可以将其限制为:3、1。**
316 | -**如果有 20 个标签,您可以将其限制为:10, 5, 4, 2, 1。**
317 | -**如果有 15 个标签,您可以将其限制为:5、3、1。**
318 |
319 | #### 在某些情况下,使用 x_axis_label_count 参数可能不足以满足您的需求。在这种情况下,您可以利用
x_axis_display_values_indices 参数来精确控制 x 轴上显示的值。
320 |
321 | - #### y_axis_label_count
322 | 默认情况下,如果将 y 轴值设置为 -100 到 100 范围,则 y 轴上将仅显示极值(-100 和 100 两个数字)。但是,您可以选择使用 y_axis_label_count 参数调整显示的标签数量。
323 | 例如,如果将 y_axis_label_count 设置为 3,系统会将 y 轴范围(-100 到 100)划分为相等的间隔,并按这些间隔显示标签。因此,对于本例,标签计数为 3,您可能会看到 -100、0 和 100 处的标签。
324 | 总之,调整 y_axis_label_count 参数允许您控制 y 轴上显示的标签数量,从而可以根据您的偏好和要求灵活地自定义可视化效果。
325 |
326 |
327 |
328 |
329 |
330 |
331 | ``` python
332 | chart = ctkchart.CTkLineChart(
333 | master=any_widget,
334 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
335 | y_axis_values=(-100, 100),
336 | x_axis_label_count=4,
337 | y_axis_label_count=10
338 | )
339 | ```
340 |
341 | ---
342 |
343 |
344 |
345 |
346 |
347 | - #### x_axis_display_values_indices
348 | 假设您有一组代表从 2018 年到 2025 年的 x 轴值:(2018、2019、2020、2021、2022、2023、2024、2025)。通常,所有这些值都会显示在 x 轴上。
349 | 但是,在某些情况下,您可能只想显示特定年份而不是全部。在这种情况下,您可以使用 x_axis_display_values_indices 参数来控制在 x 轴上显示哪些值。
350 | 例如,如果您只想显示 2019 年、2022 年和 2025 年,则可以在 x_axis_display_values_indices 参数中指定它们的索引。因此,如果 2019 年的索引为 1、2022 年为 4、2025 年为 7(假设基于 0 的索引),则您可以将 x_axis_display_values_indices 设置为 (1, 4, 7)。
351 | 这样,通过设置要显示的值的索引,您可以精确控制可视化中 X 轴上显示的值,从而允许您根据您的特定要求对其进行定制。
352 |
353 |
354 |
355 |
356 |
357 |
358 | ``` python
359 | chart = ctkchart.CTkLineChart(
360 | master=any_widget,
361 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
362 | y_axis_values=(-100, 100),
363 | x_axis_display_values_indices=(1, 4, 7)
364 | )
365 | ```
366 |
367 | ---
368 |
369 |
370 |
371 |
372 |
373 | - #### x_axis_data_position
374 | x_axis_data_position 参数确定 x_axis_data 的文字布局。
375 |
376 | 它有两个支持的值:
377 | - "top"
378 | - "side"
379 |
380 | **注意:“top”是默认位置**
381 |
382 | - #### y_axis_data_position
383 | y_axis_data_position 参数确定 y_axis_data 的文字布局。
384 |
385 | 它有两个支持的值:
386 | - "top"
387 | - "side"
388 |
389 | **注意:“top”是默认位置**
390 |
391 |
392 |
393 | 在"top"、"side"之间进行选择分别确定 x/y_axis_data 是水平放置在数据点上方还是垂直放置在数据点旁边。此参数允许您根据您的喜好和可用空间自定义折线图的布局。
394 |
395 |
396 |
397 |
398 |
399 |
400 | ``` python
401 | chart = ctkchart.CTkLineChart(
402 | master=any_widget,
403 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
404 | y_axis_values=(-100, 100),
405 | x_axis_data_position="side",
406 | y_axis_data_position="top"
407 | )
408 | ```
409 |
410 | ---
411 |
412 |
413 |
414 |
415 |
416 | - #### y_axis_precision
417 | y_axis_ precision 参数控制 y 轴上的值显示的小数位数。
418 | **注意:1 是默认精度**
419 | 例如:
420 | - 如果将 y_axis_precision 设置为 0,则 y 轴上的值将显示为整数。
421 | - 如果将 y_axis_precision 设置为 1,则 y 轴上的值将显示一位小数。
422 | - 如果将 y_axis_precision 设置为 2,则 y 轴上的值将显示两位小数。
423 |
424 |
425 | 此外 :
426 | - **调整 y_axis_ precision 参数允许您控制折线图中 y 轴值的精度级别。当处理需要特定精度的数据或当您想要通过减少显示的小数位数来提高折线图的可读性时,此参数特别有用。**
427 |
428 |
429 |
430 |
431 |
432 |
433 | ``` python
434 | chart = ctkchart.CTkLineChart(
435 | master=any_widget,
436 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
437 | y_axis_values=(-100, 100),
438 | y_axis_label_count=12,
439 | y_axis_precision=4,
440 | )
441 | ```
442 |
443 | ---
444 |
445 |
446 |
447 |
448 |
449 | - #### axis_font_style
450 | 指 x 和 y 轴值的字体样式
451 |
452 | - #### x_axis_font_color
453 | 指 x 轴值的颜色
454 |
455 | - #### y_axis_font_color
456 | 指 y 轴值的颜色
457 |
458 |
459 |
460 |
461 |
462 |
463 | ``` python
464 | chart = ctkchart.CTkLineChart(
465 | master=any_widget,
466 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
467 | y_axis_values=(-100, 100),
468 | x_axis_font_color="#00FF00",
469 | y_axis_font_color="#FF0000",
470 | axis_font_style=("arial", 13, "bold")
471 | )
472 | ```
473 |
474 | ---
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 | - #### x_axis_section_count
483 | x_axis_section_count 参数定义折线图中 x 轴范围将划分为的部分或间隔的数量。
484 | **这里有更清晰的细分:**
485 | - 假设 x 轴上有一系列值,例如从 2018 年到 2025 年。默认情况下,此范围可能表示为连续线,没有标记任何特定部分或间隔。
486 | - 但是,如果将 x_axis_section_count 设置为一个值,例如 8,则意味着您想要将此 x 轴范围划分为等间距的部分或间隔。每个部分将代表总 x 轴范围的一个子集。
487 | - 调整 x_axis_section_count 参数允许您控制折线图中 x 轴的粒度,使查看者更容易解释数据并识别特定间隔内的趋势。
488 |
489 |
490 |
491 | - #### y_axis_section_count
492 | y_axis_section_count 参数定义折线图中 y 轴范围将划分为的部分或间隔的数量。
493 | **请参阅:
x_axis_section_count** 了解更多...
494 |
495 | - #### x_axis_section_color
496 | 指 y 轴网格线的颜色
497 |
498 | - #### y_axis_section_color
499 | 指 x 轴网格线的颜色
500 |
501 |
502 |
503 |
504 |
505 |
506 | ``` python
507 | chart = ctkchart.CTkLineChart(
508 | master=any_widget,
509 | x_axis_section_count=8,
510 | y_axis_section_count=5,
511 | x_axis_section_color="#2C2C2C",
512 | y_axis_section_color="#2C2C2C"
513 | )
514 | ```
515 |
516 | ---
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 | - #### x_axis_section_style
525 | x_axis_section_style 参数允许您定义折线图中沿 x 轴的部分的视觉样式。
526 |
527 | - 支持的样式:
528 | - "dashed": 当您将 x_axis_section_style 设置为“dashed”时,沿 x 轴的剖面将使用虚线显示。
529 | - "normal": 相反,当 x_axis_section_style 设置为“正常”时,沿 x 轴的截面将使用实线显示。
530 |
531 |
532 | **注意:"normal"是默认样式。**
533 |
534 |
535 |
536 | - #### y_axis_section_style
537 | 与 x_axis_section_style 工作方式相同,
538 | 有关更多信息,请参阅
x_axis_section_style
539 |
540 |
541 |
542 | - #### x_axis_section_style_type
543 | x_axis_section_style_type 参数是一个包含两个整数值的元组,指定当 x_axis_section_style 设置为“dashed”时使用的破折号样式。
544 | 例如:
545 | - 如果将 x_axis_section_style_type 设置为 (20, 10),则意味着:
546 | - 每个破折号的宽度为 20 像素。
547 | - 破折号之间的间距为 10
548 |
549 |
550 |
551 | 这些值确定用于表示沿 x 轴的部分的虚线或标记的视觉外观。通过调整这些值,您可以根据您的偏好或可视化要求自定义虚线部分的外观。
552 |
553 |
554 |
555 | - #### y_axis_section_style_type
556 | 与 x_axis_section_style_type 工作相同,
557 | 请参阅
x_axis_section_style_type 了解更多信息
558 |
559 |
560 |
561 |
562 |
563 |
564 | ``` python
565 | chart = ctkchart.CTkLineChart(
566 | master=any_widget,
567 | x_axis_section_count=8,
568 | y_axis_section_count=5,
569 | x_axis_section_style="dashed",
570 | x_axis_section_style_type=(20,10),
571 | y_axis_section_style="dashed",
572 | y_axis_section_style_type=(20,10),
573 | )
574 | ```
575 |
576 | ---
577 |
578 |
579 |
580 |
581 |
582 |
583 | - #### x_axis_point_spacing
584 | x_axis_point_spacing 参数允许您手动设置 x 轴上点之间的间距,通常以像素为单位测量。但是,如果您不手动设置该参数,则会根据 x_axis_values 的长度自动计算。
585 |
586 | **注意:"auto"是默认值。**
587 |
588 |
589 | - 将特定值配置为 x_axis_point_spacing 后,您可以通过将其配置为"auto"来重置值以设置默认值。
590 |
591 | ``` python
592 | chart.configure(
593 | x_axis_point_spacing="auto"
594 | )
595 | ```
596 |
597 |
598 |
599 |
600 |
601 |
602 | ``` python
603 | chart = ctkchart.CTkLineChart(
604 | master=any_widget,
605 | x_axis_point_spacing="auto"
606 | )
607 | ```
608 |
609 | x_axis_point_spacing 参数是根据 x_axis_values 元组的长度自动计算的。这意味着 x 轴上点之间的间距是通过将折线图的宽度除以 x_axis_values 列表的长度来确定的。
610 |
611 |
612 |
613 |
614 |
615 |
616 | 当您将 x_axis_point_spacing 参数设置为特定值(例如 40)时,这意味着您已手动将 x 轴上的点之间的间距指定为 40 个单位(例如像素)。在这种情况下,无论 x_axis_values 元组的长度如何,折线图都将在 x 轴上的每个点之间使用用户定义的 40 个单位的间距。
617 |
618 | ``` python
619 | chart = ctkchart.CTkLineChart(
620 | master=any_widget,
621 | x_axis_point_spacing=40
622 | )
623 | ```
624 |
625 | ---
626 |
627 |
628 |
629 | ### CTkLine
630 |
631 |
632 |
633 | - #### color
634 | 指的是线条的颜色。
635 |
636 | - #### size
637 | 指线条的尺寸(粗细)。
638 | **注:1 为默认尺寸**
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 | ``` python
647 | line = ctkchart.CTkLine(
648 | master=chart,
649 | color="#30ACC7",
650 | size=5
651 | )
652 | ```
653 |
654 | ---
655 |
656 |
657 |
658 |
659 |
660 | - #### style
661 | style 参数允许您定义线条的视觉样式。
662 |
663 | - 支持的样式:
664 | - "dashed": 当样式设置为"dashed"时,折线条显示为虚线。
665 | - "dotted": 当样式设置为"dotted"时,折线显示为点虚线。
666 | - "normal": 当样式设置为"normal"时,线条显示为实线。
667 |
668 | **注意:"normal"是默认样式。**
669 |
670 |
671 |
672 |
673 |
674 |
675 | ``` python
676 | line = ctkchart.CTkLine(
677 | master=chart,
678 | line_style="dashed"
679 | )
680 | ```
681 |
682 | ---
683 |
684 |
685 |
686 |
687 |
688 | - #### style_type
689 | style_type 参数是一个包含两个整数值的元组,指定样式设置为"dashed"或"dotted"时使用的破折号和点的样式。
690 |
691 | 例如:
692 | - 如果将 style_type 设置为 (20, 10),则意味着:
693 | - 每个破折号的宽度或每个点的大小为 20 像素。
694 | - 破折号或点之间的间距为 10 个像素。
695 |
696 | **注意 在"dotted"风格下 , size 参数无关紧要,因为点的大小是由 style_type 元组确定的固定大小。**
697 | **注意 在"normal"风格下,style_type 参数无效。**
698 |
699 |
700 |
701 |
702 |
703 |
704 | ``` python
705 | line = ctkchart.CTkLine(
706 | master=chart,
707 | line_style="dashed",
708 | line_style_type=(10,2)
709 | )
710 | ```
711 |
712 | ---
713 |
714 |
715 |
716 |
717 |
718 | - #### point_highlight
719 | point_highlight 参数用于控制点高亮。
720 |
721 | - 支持的值:
722 | - "enabled": 启用点高亮显示。
723 | - "disabled": 禁用点高亮显示。
724 |
725 | - #### point_highlight_size
726 | point_highlight_size 用于设置高亮点的大小。
727 |
728 | - #### point_highlight_color
729 | 高亮点的颜色。
730 |
731 |
732 |
733 |
734 |
735 |
736 | ``` python
737 | line = ctkchart.CTkLine(
738 | master=chart,
739 | point_highlight="enabled",
740 | point_highlight_color="#80CCFF",
741 | point_highlight_size=8
742 | )
743 | ```
744 |
745 | ---
746 |
747 |
748 |
749 |
750 |
751 | - #### fill
752 | fill 参数用于控制是否启用或禁用行填充。
753 |
754 | - 支持的值:
755 | - "enabled": 启用线条填充。
756 | - "disabled": 禁用线条填充。
757 |
758 | - #### fill_color
759 | fill_color 参数用于指定填充的颜色。
760 |
761 |
762 |
763 |
764 |
765 |
766 | ``` python
767 | line = ctkchart.CTkLine(
768 | master=chart,
769 | fill="enabled",
770 | fill_color="#5D6DB6"
771 | )
772 | ```
773 |
774 |
775 |
776 |
777 |
778 | ---
779 |
780 |
781 |
782 | ## 动态颜色变化
783 |
784 | ***对于 ctkchart 中涉及颜色的每个参数,有两种写法***:
785 |
786 | - 代表颜色的单个字符串。
787 | - 两个字符串的元组,其中第一个字符串表示浅色主题的颜色,第二个字符串表示深色主题的颜色。
788 |
789 |
790 |
791 |
792 |
793 | ---
794 |
795 |
**回到顶部** |
**使用指南** |
**参数说明** |
**查看新功能**
796 |
797 | ## [例子](https://github.com/Thisal-D/ctkchart/tree/main/template(s))
798 |
799 |
816 |
817 |
818 |
819 | ---
820 |
821 | ## 链接
822 |
823 | **PyPi.org** : ctkchart
824 |
825 | **GitHub.com** : ctkchart
826 |
827 | ---
828 |
829 | ## 翻译贡献
830 |
831 | **翻译支持** : [有语](https://github.com/childeyouyu)
832 |
833 | **Translation by** : [youyu](https://github.com/childeyouyu)
--------------------------------------------------------------------------------
/Tests/Main - Test.py:
--------------------------------------------------------------------------------
1 | import ctkchart
2 | import customtkinter as ctk
3 | import random
4 |
5 | root = ctk.CTk()
6 | root.geometry("1900x900")
7 |
8 | data = ([x for x in range(0,1001)])
9 | x_axis_values = tuple([x for x in range(1,21)])
10 | line_chart = ctkchart.CTkLineChart(master=root,
11 | x_axis_values=x_axis_values, y_axis_values=(0, 1000))
12 | line_chart.pack()
13 |
14 |
15 | line = ctkchart.CTkLine(master=line_chart, style="dashed", style_type=(10,5), size=1, color=("#404040", "lightblue"), fill="enabled",
16 | point_highlight="enabled", point_highlight_size=5, point_highlight_color=("#404040", "lightblue"))
17 |
18 | def loop():
19 | line_chart.show_data(line=line ,data=[random.choice(data)])
20 | root.after(100, loop)
21 | loop()
22 |
23 |
24 | frame = ctk.CTkScrollableFrame(master=root, width=1000, height=900, fg_color=("#FFFFFF","#151515"))
25 | frame.pack(pady=100)
26 |
27 | def line_chart_configure(**kwrgs):
28 | line_chart.configure(**kwrgs)
29 |
30 | def line_configure(**kwrgs):
31 | line.configure(**kwrgs)
32 |
33 | row = 1
34 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Line Chart Attributes : ", font=("Arial",25,"bold")).grid(row=row, column=1)
35 | row += 1
36 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Width : ").grid(row=row, column=1)
37 | column = 2
38 | for width in range(900,1600,100):
39 | ctk.CTkButton(master=frame, text="{}".format(width), width=90, height=30, command=lambda width_=width: line_chart_configure(width=width_)).grid(row=row, column=column, padx=10, pady=2)
40 | column += 1
41 |
42 | row += 1
43 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
44 | row += 1
45 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Height : ").grid(row=row, column=1)
46 | column = 2
47 | for height in range(350,900,50):
48 | ctk.CTkButton(master=frame, text="{}".format(height), width=90, height=30, command=lambda height_=height: line_chart_configure(height=height_)).grid(row=row, column=column, padx=10, pady=2)
49 | column += 1
50 |
51 | row += 1
52 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
53 | row += 1
54 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Axis Size : ").grid(row=row, column=1)
55 | column = 2
56 | for axis_size in range(1,9,1):
57 | ctk.CTkButton(master=frame, text="{}".format(axis_size), width=90, height=30, command=lambda axis_size_=axis_size: line_chart_configure(axis_size=axis_size_)).grid(row=row, column=column, padx=10, pady=2)
58 | column += 1
59 |
60 | row += 1
61 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
62 | row += 1
63 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Labels : ").grid(row=row, column=1)
64 | column = 2
65 | for y_axis_label_count in range(0,14,2):
66 | ctk.CTkButton(master=frame, text="{}".format(y_axis_label_count), width=90, height=30, command=lambda y_axis_label_count_=y_axis_label_count: line_chart_configure(y_axis_label_count=y_axis_label_count_)).grid(row=row, column=column, padx=10, pady=2)
67 | column += 1
68 |
69 | row += 1
70 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
71 | row += 1
72 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Labels : ").grid(row=row, column=1)
73 | column = 2
74 | for x_axis_label_count in [0, 1, 2, 4, 5, 10, 20]:
75 | ctk.CTkButton(master=frame, text="{}".format(x_axis_label_count), width=90, height=30, command=lambda x_axis_label_count_=x_axis_label_count: line_chart_configure(x_axis_label_count=x_axis_label_count_)).grid(row=row, column=column, padx=10, pady=2)
76 | column += 1
77 |
78 | row += 1
79 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
80 | row += 1
81 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Precision : ").grid(row=row, column=1)
82 | column = 2
83 | for y_axis_precision in range(0,9,1):
84 | ctk.CTkButton(master=frame, text="{}".format(y_axis_precision), width=90, height=30, command=lambda y_axis_precision_=y_axis_precision: line_chart_configure(y_axis_precision=y_axis_precision_)).grid(row=row, column=column, padx=10, pady=2)
85 | column += 1
86 |
87 | row += 1
88 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
89 | row += 1
90 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis values : ").grid(row=row, column=1)
91 | column = 2
92 | values = [(-1000, 1000), (0, 1000), (-2000, 1000), (0, 2000), (-5000,2000)]
93 | for i in range(5):
94 | ctk.CTkButton(master=frame, text="{}".format(values[i]), width=90, height=30, command=lambda y_axis_values_=values[i]: line_chart_configure(y_axis_values=y_axis_values_)).grid(row=row, column=column, padx=10, pady=2)
95 | column += 1
96 |
97 | row += 1
98 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
99 | row += 1
100 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Values : ").grid(row=row, column=1)
101 | column = 2
102 | for x_axis_values in range(1, 90, 10):
103 | ctk.CTkButton(master=frame, text="range({},{})".format(x_axis_values,x_axis_values+20), width=90, height=30,
104 | command=lambda x_axis_values_=[x for x in range(x_axis_values,x_axis_values+20)]: line_chart_configure(x_axis_values=tuple(x_axis_values_))
105 | ).grid(row=row, column=column, padx=10, pady=2)
106 | column += 1
107 |
108 | row += 1
109 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
110 | row += 1
111 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Sections : ").grid(row=row, column=1)
112 | column = 2
113 | for y_axis_section_count in range(0, 14, 2):
114 | ctk.CTkButton(master=frame, text="{}".format(y_axis_section_count), width=90, height=30, command=lambda y_axis_section_count_=y_axis_section_count: line_chart_configure(y_axis_section_count=y_axis_section_count_)).grid(row=row, column=column, padx=10, pady=2)
115 | column += 1
116 |
117 | row += 1
118 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
119 | row += 1
120 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Sections : ").grid(row=row, column=1)
121 | column = 2
122 | for x_axis_section_count in range(0, 14, 2):
123 | ctk.CTkButton(master=frame, text="{}".format(x_axis_section_count), width=90, height=30, command=lambda x_axis_section_count_=x_axis_section_count: line_chart_configure(x_axis_section_count=x_axis_section_count_)).grid(row=row, column=column, padx=10, pady=2)
124 | column += 1
125 |
126 | row += 1
127 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
128 | row += 1
129 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="x axis point spacing : ").grid(row=row, column=1)
130 | ctk.CTkButton(master=frame, text="{}".format("Auto"), width=90, height=30, command=lambda : line_chart_configure(x_axis_point_spacing="auto")).grid(row=row, column=2, padx=10, pady=2)
131 | column = 3
132 | for x_axis_point_spacing in range(10, 40, 5):
133 | ctk.CTkButton(master=frame, text="{}".format(x_axis_point_spacing), width=90, height=30, command=lambda x_axis_point_spacing_=x_axis_point_spacing: line_chart_configure(x_axis_point_spacing=x_axis_point_spacing_)).grid(row=row, column=column, padx=10, pady=2)
134 | column += 1
135 |
136 | row += 1
137 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
138 | row += 1
139 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Space : ").grid(row=row, column=1)
140 | column = 2
141 | for y_space in range(0, 90, 10):
142 | ctk.CTkButton(master=frame, text="{}".format(y_space), width=90, height=30, command=lambda y_space_=y_space: line_chart_configure(y_space=y_space_)).grid(row=row, column=column, padx=10, pady=2)
143 | column += 1
144 |
145 | row += 1
146 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
147 | row += 1
148 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Space : ").grid(row=row, column=1)
149 | column = 2
150 | for x_space in range(0, 90, 10):
151 | ctk.CTkButton(master=frame, text="{}".format(x_space), width=90, height=30, command=lambda x_space_=x_space: line_chart_configure(x_space=x_space_)).grid(row=row, column=column, padx=10, pady=2)
152 | column += 1
153 |
154 | row += 1
155 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
156 | row += 1
157 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Data : ").grid(row=row, column=1)
158 | column = 2
159 | ctk.CTkButton(master=frame, text="{}".format("Y"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data="Y")).grid(row=row, column=column, padx=10, pady=2)
160 | column += 1
161 | ctk.CTkButton(master=frame, text="{}".format("Y-AXIS"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data="Y-AXIS")).grid(row=row, column=column, padx=10, pady=2)
162 |
163 | row += 1
164 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
165 | row += 1
166 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Data : ").grid(row=row, column=1)
167 | column = 2
168 | ctk.CTkButton(master=frame, text="{}".format("X"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data="X")).grid(row=row, column=column, padx=10, pady=2)
169 | column += 1
170 | ctk.CTkButton(master=frame, text="{}".format("X-AXIS"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data="X-AXIS")).grid(row=row, column=column, padx=10, pady=2)
171 |
172 | row += 1
173 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
174 | row += 1
175 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Data Position : ").grid(row=row, column=1)
176 | column = 2
177 | ctk.CTkButton(master=frame, text="{}".format("top"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_position="top")).grid(row=row, column=column, padx=10, pady=2)
178 | column += 1
179 | ctk.CTkButton(master=frame, text="{}".format("side"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_position="side")).grid(row=row, column=column, padx=10, pady=2)
180 |
181 | row += 1
182 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
183 | row += 1
184 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Data Position : ").grid(row=row, column=1)
185 | column = 2
186 | ctk.CTkButton(master=frame, text="{}".format("top"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_position="top")).grid(row=row, column=column, padx=10, pady=2)
187 | column += 1
188 | ctk.CTkButton(master=frame, text="{}".format("side"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_position="side")).grid(row=row, column=column, padx=10, pady=2)
189 |
190 | row += 1
191 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
192 | row += 1
193 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Data Font Style : ").grid(row=row, column=1)
194 | column = 2
195 | ctk.CTkButton(master=frame, text="{}".format("('arial',10,'normal')"), width=90, height=30, command=lambda:line_chart_configure(data_font_style=("arial",10,"normal"))).grid(row=row, column=column, padx=10, pady=2)
196 | column += 1
197 | ctk.CTkButton(master=frame, text="{}".format("('arial',10,'bold')"), width=90, height=30, command=lambda:line_chart_configure(data_font_style=("arial",10,"bold"))).grid(row=row, column=column, padx=10, pady=2)
198 | column += 1
199 | ctk.CTkButton(master=frame, text="{}".format("('arial',15,'normal')"), width=90, height=30, command=lambda:line_chart_configure(data_font_style=("arial",15,"normal"))).grid(row=row, column=column, padx=10, pady=2)
200 | column += 1
201 | ctk.CTkButton(master=frame, text="{}".format("('arial',15,'bold')"), width=90, height=30, command=lambda:line_chart_configure(data_font_style=("arial",15,"bold"))).grid(row=row, column=column, padx=10, pady=2)
202 |
203 | row += 1
204 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
205 | row += 1
206 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Axis Font Style : ").grid(row=row, column=1)
207 | column = 2
208 | ctk.CTkButton(master=frame, text="{}".format("('arial',10,'normal')"), width=90, height=30, command=lambda:line_chart_configure(axis_font_style=("arial",10,"normal"))).grid(row=row, column=column, padx=10, pady=2)
209 | column += 1
210 | ctk.CTkButton(master=frame, text="{}".format("('arial',10,'bold')"), width=90, height=30, command=lambda:line_chart_configure(axis_font_style=("arial",10,"bold"))).grid(row=row, column=column, padx=10, pady=2)
211 | column += 1
212 | ctk.CTkButton(master=frame, text="{}".format("('arial',12,'normal')"), width=90, height=30, command=lambda:line_chart_configure(axis_font_style=("arial",12,"normal"))).grid(row=row, column=column, padx=10, pady=2)
213 | column += 1
214 | ctk.CTkButton(master=frame, text="{}".format("('arial',12,'bold')"), width=90, height=30, command=lambda:line_chart_configure(axis_font_style=("arial",12,"bold"))).grid(row=row, column=column, padx=10, pady=2)
215 |
216 | row += 1
217 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
218 | row += 1
219 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Section Color : ").grid(row=row, column=1)
220 | column = 2
221 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
222 | column += 1
223 | ctk.CTkButton(master=frame, text="{}".format("#303030"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_color="#303030")).grid(row=row, column=column, padx=10, pady=2)
224 | column += 1
225 | ctk.CTkButton(master=frame, text="{}".format("#454545"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_color="#454545")).grid(row=row, column=column, padx=10, pady=2)
226 | column += 1
227 | ctk.CTkButton(master=frame, text="{}".format("#606060"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_color="#606060")).grid(row=row, column=column, padx=10, pady=2)
228 | column += 1
229 | ctk.CTkButton(master=frame, text="{}".format("#757575"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_color="#757575")).grid(row=row, column=column, padx=10, pady=2)
230 | column += 1
231 | ctk.CTkButton(master=frame, text="{}".format("#909090"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_color="#909090")).grid(row=row, column=column, padx=10, pady=2)
232 | column += 1
233 |
234 |
235 | row += 1
236 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
237 | row += 1
238 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Section Color : ").grid(row=row, column=1)
239 | column = 2
240 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
241 | column += 1
242 | ctk.CTkButton(master=frame, text="{}".format("#303030"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_color="#303030")).grid(row=row, column=column, padx=10, pady=2)
243 | column += 1
244 | ctk.CTkButton(master=frame, text="{}".format("#454545"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_color="#454545")).grid(row=row, column=column, padx=10, pady=2)
245 | column += 1
246 | ctk.CTkButton(master=frame, text="{}".format("#606060"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_color="#606060")).grid(row=row, column=column, padx=10, pady=2)
247 | column += 1
248 | ctk.CTkButton(master=frame, text="{}".format("#757575"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_color="#757575")).grid(row=row, column=column, padx=10, pady=2)
249 | column += 1
250 | ctk.CTkButton(master=frame, text="{}".format("#909090"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_color="#909090")).grid(row=row, column=column, padx=10, pady=2)
251 | column += 1
252 |
253 |
254 | row += 1
255 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
256 | row += 1
257 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Section Style : ").grid(row=row, column=1)
258 | column = 2
259 | ctk.CTkButton(master=frame, text="{}".format("normal"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style="normal")).grid(row=row, column=column, padx=10, pady=2)
260 | column += 1
261 | ctk.CTkButton(master=frame, text="{}".format("dashed"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style="dashed")).grid(row=row, column=column, padx=10, pady=2)
262 | column += 1
263 |
264 | row += 1
265 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
266 | row += 1
267 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Style Type : ").grid(row=row, column=1)
268 | column = 2
269 | ctk.CTkButton(master=frame, text="{}".format("(10, 5)"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style_type=(10, 5))).grid(row=row, column=column, padx=10, pady=2)
270 | column += 1
271 | ctk.CTkButton(master=frame, text="{}".format("(20, 5)"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style_type=(20, 5))).grid(row=row, column=column, padx=10, pady=2)
272 | column += 1
273 | ctk.CTkButton(master=frame, text="{}".format("(20, 10)"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style_type=(10, 20))).grid(row=row, column=column, padx=10, pady=2)
274 | column += 1
275 | ctk.CTkButton(master=frame, text="{}".format("(20, 10)"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style_type=(20, 10))).grid(row=row, column=column, padx=10, pady=2)
276 | column += 1
277 | ctk.CTkButton(master=frame, text="{}".format("(5, 5)"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style_type=(5, 5))).grid(row=row, column=column, padx=10, pady=2)
278 | column += 1
279 | ctk.CTkButton(master=frame, text="{}".format("(20, 20)"), width=90, height=30, command=lambda:line_chart_configure(x_axis_section_style_type=(20, 20))).grid(row=row, column=column, padx=10, pady=2)
280 | column += 1
281 |
282 | row += 1
283 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
284 | row += 1
285 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Section Style : ").grid(row=row, column=1)
286 | column = 2
287 | ctk.CTkButton(master=frame, text="{}".format("normal"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style="normal")).grid(row=row, column=column, padx=10, pady=2)
288 | column += 1
289 | ctk.CTkButton(master=frame, text="{}".format("dashed"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style="dashed")).grid(row=row, column=column, padx=10, pady=2)
290 | column += 1
291 |
292 | row += 1
293 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
294 | row += 1
295 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Style Type : ").grid(row=row, column=1)
296 | column = 2
297 | ctk.CTkButton(master=frame, text="{}".format("(10, 5)"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style_type=(10, 5))).grid(row=row, column=column, padx=10, pady=2)
298 | column += 1
299 | ctk.CTkButton(master=frame, text="{}".format("(20, 5)"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style_type=(20, 5))).grid(row=row, column=column, padx=10, pady=2)
300 | column += 1
301 | ctk.CTkButton(master=frame, text="{}".format("(20, 10)"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style_type=(10, 20))).grid(row=row, column=column, padx=10, pady=2)
302 | column += 1
303 | ctk.CTkButton(master=frame, text="{}".format("(20, 10)"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style_type=(20, 10))).grid(row=row, column=column, padx=10, pady=2)
304 | column += 1
305 | ctk.CTkButton(master=frame, text="{}".format("(5, 5)"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style_type=(5, 5))).grid(row=row, column=column, padx=10, pady=2)
306 | column += 1
307 | ctk.CTkButton(master=frame, text="{}".format("(20, 20)"), width=90, height=30, command=lambda:line_chart_configure(y_axis_section_style_type=(20, 20))).grid(row=row, column=column, padx=10, pady=2)
308 | column += 1
309 |
310 |
311 | row += 1
312 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
313 | row += 1
314 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Axis Color : ").grid(row=row, column=1)
315 | column = 2
316 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(axis_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
317 | column += 1
318 | ctk.CTkButton(master=frame, text="{}".format("#151515"), width=90, height=30, command=lambda:line_chart_configure(axis_color="#151515")).grid(row=row, column=column, padx=10, pady=2)
319 | column += 1
320 | ctk.CTkButton(master=frame, text="{}".format("#252525"), width=90, height=30, command=lambda:line_chart_configure(axis_color="#252525")).grid(row=row, column=column, padx=10, pady=2)
321 | column += 1
322 | ctk.CTkButton(master=frame, text="{}".format("#505050"), width=90, height=30, command=lambda:line_chart_configure(axis_color="#505050")).grid(row=row, column=column, padx=10, pady=2)
323 | column += 1
324 | ctk.CTkButton(master=frame, text="{}".format("#909090"), width=90, height=30, command=lambda:line_chart_configure(axis_color="#909090")).grid(row=row, column=column, padx=10, pady=2)
325 | column += 1
326 | ctk.CTkButton(master=frame, text="{}".format("#FFFFFF"), width=90, height=30, command=lambda:line_chart_configure(axis_color="#FFFFFF")).grid(row=row, column=column, padx=10, pady=2)
327 | column += 1
328 |
329 | row += 1
330 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
331 | row += 1
332 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="BG Color : ").grid(row=row, column=1)
333 | column = 2
334 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(bg_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
335 | column += 1
336 | ctk.CTkButton(master=frame, text="{}".format("#151515"), width=90, height=30, command=lambda:line_chart_configure(bg_color="#151515")).grid(row=row, column=column, padx=10, pady=2)
337 | column += 1
338 | ctk.CTkButton(master=frame, text="{}".format("#252525"), width=90, height=30, command=lambda:line_chart_configure(bg_color="#252525")).grid(row=row, column=column, padx=10, pady=2)
339 | column += 1
340 | ctk.CTkButton(master=frame, text="{}".format("#505050"), width=90, height=30, command=lambda:line_chart_configure(bg_color="#505050")).grid(row=row, column=column, padx=10, pady=2)
341 | column += 1
342 | ctk.CTkButton(master=frame, text="{}".format("#707070"), width=90, height=30, command=lambda:line_chart_configure(bg_color="#707070")).grid(row=row, column=column, padx=10, pady=2)
343 | column += 1
344 | ctk.CTkButton(master=frame, text="{}".format("#FFFFFF"), width=90, height=30, command=lambda:line_chart_configure(bg_color="#FFFFFF")).grid(row=row, column=column, padx=10, pady=2)
345 | column += 1
346 |
347 | row += 1
348 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
349 | row += 1
350 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="FG Color : ").grid(row=row, column=1)
351 | column = 2
352 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(fg_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
353 | column += 1
354 | ctk.CTkButton(master=frame, text="{}".format("#151515"), width=90, height=30, command=lambda:line_chart_configure(fg_color="#151515")).grid(row=row, column=column, padx=10, pady=2)
355 | column += 1
356 | ctk.CTkButton(master=frame, text="{}".format("#252525"), width=90, height=30, command=lambda:line_chart_configure(fg_color="#252525")).grid(row=row, column=column, padx=10, pady=2)
357 | column += 1
358 | ctk.CTkButton(master=frame, text="{}".format("#505050"), width=90, height=30, command=lambda:line_chart_configure(fg_color="#505050")).grid(row=row, column=column, padx=10, pady=2)
359 | column += 1
360 | ctk.CTkButton(master=frame, text="{}".format("#707070"), width=90, height=30, command=lambda:line_chart_configure(fg_color="#707070")).grid(row=row, column=column, padx=10, pady=2)
361 | column += 1
362 | ctk.CTkButton(master=frame, text="{}".format("#FFFFFF"), width=90, height=30, command=lambda:line_chart_configure(fg_color="#FFFFFF")).grid(row=row, column=column, padx=10, pady=2)
363 | column += 1
364 |
365 | row += 1
366 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
367 | row += 1
368 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Font Color : ").grid(row=row, column=1)
369 | column = 2
370 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(y_axis_font_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
371 | column += 1
372 | ctk.CTkButton(master=frame, text="{}".format("#151515"), width=90, height=30, command=lambda:line_chart_configure(y_axis_font_color="#151515")).grid(row=row, column=column, padx=10, pady=2)
373 | column += 1
374 | ctk.CTkButton(master=frame, text="{}".format("#252525"), width=90, height=30, command=lambda:line_chart_configure(y_axis_font_color="#252525")).grid(row=row, column=column, padx=10, pady=2)
375 | column += 1
376 | ctk.CTkButton(master=frame, text="{}".format("#505050"), width=90, height=30, command=lambda:line_chart_configure(y_axis_font_color="#505050")).grid(row=row, column=column, padx=10, pady=2)
377 | column += 1
378 | ctk.CTkButton(master=frame, text="{}".format("#707070"), width=90, height=30, command=lambda:line_chart_configure(y_axis_font_color="#707070")).grid(row=row, column=column, padx=10, pady=2)
379 | column += 1
380 | ctk.CTkButton(master=frame, text="{}".format("#FFFFFF"), width=90, height=30, command=lambda:line_chart_configure(y_axis_font_color="#FFFFFF")).grid(row=row, column=column, padx=10, pady=2)
381 | column += 1
382 |
383 | row += 1
384 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
385 | row += 1
386 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Font Color : ").grid(row=row, column=1)
387 | column = 2
388 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(x_axis_font_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
389 | column += 1
390 | ctk.CTkButton(master=frame, text="{}".format("#151515"), width=90, height=30, command=lambda:line_chart_configure(x_axis_font_color="#151515")).grid(row=row, column=column, padx=10, pady=2)
391 | column += 1
392 | ctk.CTkButton(master=frame, text="{}".format("#252525"), width=90, height=30, command=lambda:line_chart_configure(x_axis_label_count_axis_font_color="#252525")).grid(row=row, column=column, padx=10, pady=2)
393 | column += 1
394 | ctk.CTkButton(master=frame, text="{}".format("#505050"), width=90, height=30, command=lambda:line_chart_configure(x_axis_font_color="#505050")).grid(row=row, column=column, padx=10, pady=2)
395 | column += 1
396 | ctk.CTkButton(master=frame, text="{}".format("#707070"), width=90, height=30, command=lambda:line_chart_configure(x_axis_font_color="#707070")).grid(row=row, column=column, padx=10, pady=2)
397 | column += 1
398 | ctk.CTkButton(master=frame, text="{}".format("#FFFFFF"), width=90, height=30, command=lambda:line_chart_configure(x_axis_font_color="#FFFFFF")).grid(row=row, column=column, padx=10, pady=2)
399 | column += 1
400 |
401 | row += 1
402 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
403 | row += 1
404 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Y Axis Data Font Color : ").grid(row=row, column=1)
405 | column = 2
406 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_font_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
407 | column += 1
408 | ctk.CTkButton(master=frame, text="{}".format("#151515"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_font_color="#151515")).grid(row=row, column=column, padx=10, pady=2)
409 | column += 1
410 | ctk.CTkButton(master=frame, text="{}".format("#252525"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_font_color="#252525")).grid(row=row, column=column, padx=10, pady=2)
411 | column += 1
412 | ctk.CTkButton(master=frame, text="{}".format("#505050"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_font_color="#505050")).grid(row=row, column=column, padx=10, pady=2)
413 | column += 1
414 | ctk.CTkButton(master=frame, text="{}".format("#707070"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_font_color="#707070")).grid(row=row, column=column, padx=10, pady=2)
415 | column += 1
416 | ctk.CTkButton(master=frame, text="{}".format("#FFFFFF"), width=90, height=30, command=lambda:line_chart_configure(y_axis_data_font_color="#FFFFFF")).grid(row=row, column=column, padx=10, pady=2)
417 | column += 1
418 |
419 | row += 1
420 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
421 | row += 1
422 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="X Axis Data Font Color : ").grid(row=row, column=1)
423 | column = 2
424 | ctk.CTkButton(master=frame, text="{}".format("#000000"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_font_color="#000000")).grid(row=row, column=column, padx=10, pady=2)
425 | column += 1
426 | ctk.CTkButton(master=frame, text="{}".format("#151515"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_font_color="#151515")).grid(row=row, column=column, padx=10, pady=2)
427 | column += 1
428 | ctk.CTkButton(master=frame, text="{}".format("#252525"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_font_color="#252525")).grid(row=row, column=column, padx=10, pady=2)
429 | column += 1
430 | ctk.CTkButton(master=frame, text="{}".format("#505050"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_font_color="#505050")).grid(row=row, column=column, padx=10, pady=2)
431 | column += 1
432 | ctk.CTkButton(master=frame, text="{}".format("#707070"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_font_color="#707070")).grid(row=row, column=column, padx=10, pady=2)
433 | column += 1
434 | ctk.CTkButton(master=frame, text="{}".format("#FFFFFF"), width=90, height=30, command=lambda:line_chart_configure(x_axis_data_font_color="#FFFFFF")).grid(row=row, column=column, padx=10, pady=2)
435 | column += 1
436 |
437 | row += 1
438 | ctk.CTkFrame(master=frame ,height=10, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
439 |
440 | row += 1
441 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Line Attributes : ", font=("Arial",25,"bold")).grid(row=row, column=1)
442 |
443 | row += 1
444 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
445 | row += 1
446 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Size : ").grid(row=row, column=1)
447 | column = 2
448 | ctk.CTkButton(master=frame, text="{}".format(1), width=90, height=30, command=lambda:line_configure(size=1)).grid(row=row, column=column, padx=10, pady=2)
449 | column += 1
450 | ctk.CTkButton(master=frame, text="{}".format(2), width=90, height=30, command=lambda:line_configure(size=2)).grid(row=row, column=column, padx=10, pady=2)
451 | column += 1
452 | ctk.CTkButton(master=frame, text="{}".format(4), width=90, height=30, command=lambda:line_configure(size=4)).grid(row=row, column=column, padx=10, pady=2)
453 |
454 | row += 1
455 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
456 | row += 1
457 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Style : ").grid(row=row, column=1)
458 | column = 2
459 | ctk.CTkButton(master=frame, text="{}".format("line"), width=90, height=30, command=lambda:line_configure(style="normal")).grid(row=row, column=column, padx=10, pady=2)
460 | column += 1
461 | ctk.CTkButton(master=frame, text="{}".format("dashed"), width=90, height=30, command=lambda:line_configure(style="dashed")).grid(row=row, column=column, padx=10, pady=2)
462 | column += 1
463 | ctk.CTkButton(master=frame, text="{}".format("dotted"), width=90, height=30, command=lambda:line_configure(style="dotted")).grid(row=row, column=column, padx=10, pady=2)
464 |
465 |
466 | row += 1
467 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
468 | row += 1
469 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Style Type : ").grid(row=row, column=1)
470 | column = 2
471 | ctk.CTkButton(master=frame, text="{}".format("(5,10)"), width=90, height=30, command=lambda:line_configure(style_type=(5,10))).grid(row=row, column=column, padx=10, pady=2)
472 | column += 1
473 | ctk.CTkButton(master=frame, text="{}".format("(20,10)"), width=90, height=30, command=lambda:line_configure(style_type=(20,10))).grid(row=row, column=column, padx=10, pady=2)
474 | column += 1
475 | ctk.CTkButton(master=frame, text="{}".format("(10,5)"), width=90, height=30, command=lambda:line_configure(style_type=(10,5))).grid(row=row, column=column, padx=10, pady=2)
476 | column += 1
477 | ctk.CTkButton(master=frame, text="{}".format("(10,30)"), width=90, height=30, command=lambda:line_configure(style_type=(10,30))).grid(row=row, column=column, padx=10, pady=2)
478 | column += 1
479 | ctk.CTkButton(master=frame, text="{}".format("(1,1)"), width=90, height=30, command=lambda:line_configure(style_type=(1,1))).grid(row=row, column=column, padx=10, pady=2)
480 |
481 |
482 |
483 | row += 1
484 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
485 | row += 1
486 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Color : ").grid(row=row, column=1)
487 | column = 2
488 | ctk.CTkButton(master=frame, text="{}".format("#FF0000"), width=90, height=30, command=lambda:line_configure(color="#FF0000")).grid(row=row, column=column, padx=10, pady=2)
489 | column += 1
490 | ctk.CTkButton(master=frame, text="{}".format("00FF00"), width=90, height=30, command=lambda:line_configure(color="#00FF00")).grid(row=row, column=column, padx=10, pady=2)
491 | column += 1
492 | ctk.CTkButton(master=frame, text="{}".format("#0000FF"), width=90, height=30, command=lambda:line_configure(color="#0000FF")).grid(row=row, column=column, padx=10, pady=2)
493 | column += 1
494 | ctk.CTkButton(master=frame, text="{}".format("#FF00FF"), width=90, height=30, command=lambda:line_configure(color="#FF00FF")).grid(row=row, column=column, padx=10, pady=2)
495 | column += 1
496 | ctk.CTkButton(master=frame, text="{}".format("#00FFFF"), width=90, height=30, command=lambda:line_configure(color="#00FFFF")).grid(row=row, column=column, padx=10, pady=2)
497 |
498 |
499 |
500 | row += 1
501 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
502 | row += 1
503 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Point Hightlight : ").grid(row=row, column=1)
504 | column = 2
505 | ctk.CTkButton(master=frame, text="{}".format("enabled"), width=90, height=30, command=lambda:line_configure(point_highlight="enabled")).grid(row=row, column=column, padx=10, pady=2)
506 | column += 1
507 | ctk.CTkButton(master=frame, text="{}".format("disabled"), width=90, height=30, command=lambda:line_configure(point_highlight="disabled")).grid(row=row, column=column, padx=10, pady=2)
508 | column += 1
509 |
510 |
511 |
512 | row += 1
513 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
514 | row += 1
515 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Point Hightlight Size : ").grid(row=row, column=1)
516 | column = 2
517 | ctk.CTkButton(master=frame, text="{}".format("5"), width=90, height=30, command=lambda:line_configure(point_highlight_size=5)).grid(row=row, column=column, padx=10, pady=2)
518 | column += 1
519 | ctk.CTkButton(master=frame, text="{}".format("10"), width=90, height=30, command=lambda:line_configure(point_highlight_size=10)).grid(row=row, column=column, padx=10, pady=2)
520 | column += 1
521 | ctk.CTkButton(master=frame, text="{}".format("15"), width=90, height=30, command=lambda:line_configure(point_highlight_size=15)).grid(row=row, column=column, padx=10, pady=2)
522 | column += 1
523 | ctk.CTkButton(master=frame, text="{}".format("20"), width=90, height=30, command=lambda:line_configure(point_highlight_size=20)).grid(row=row, column=column, padx=10, pady=2)
524 | column += 1
525 | ctk.CTkButton(master=frame, text="{}".format("25"), width=90, height=30, command=lambda:line_configure(point_highlight_size=25)).grid(row=row, column=column, padx=10, pady=2)
526 |
527 |
528 |
529 | row += 1
530 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
531 | row += 1
532 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Point Hightlight Color : ").grid(row=row, column=1)
533 | column = 2
534 | ctk.CTkButton(master=frame, text="{}".format("#FF0000"), width=90, height=30, command=lambda:line_configure(point_highlight_color="#FF0000")).grid(row=row, column=column, padx=10, pady=2)
535 | column += 1
536 | ctk.CTkButton(master=frame, text="{}".format("00FF00"), width=90, height=30, command=lambda:line_configure(point_highlight_color="#00FF00")).grid(row=row, column=column, padx=10, pady=2)
537 | column += 1
538 | ctk.CTkButton(master=frame, text="{}".format("#0000FF"), width=90, height=30, command=lambda:line_configure(point_highlight_color="#0000FF")).grid(row=row, column=column, padx=10, pady=2)
539 | column += 1
540 | ctk.CTkButton(master=frame, text="{}".format("#FF00FF"), width=90, height=30, command=lambda:line_configure(point_highlight_color="#FF00FF")).grid(row=row, column=column, padx=10, pady=2)
541 | column += 1
542 | ctk.CTkButton(master=frame, text="{}".format("#00FFFF"), width=90, height=30, command=lambda:line_configure(point_highlight_color="#00FFFF")).grid(row=row, column=column, padx=10, pady=2)
543 |
544 |
545 | row += 1
546 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
547 | row += 1
548 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Fill : ").grid(row=row, column=1)
549 | column = 2
550 | ctk.CTkButton(master=frame, text="{}".format("enabled"), width=90, height=30, command=lambda:line_configure(fill="enabled")).grid(row=row, column=column, padx=10, pady=2)
551 | column += 1
552 | ctk.CTkButton(master=frame, text="{}".format("disabled"), width=90, height=30, command=lambda:line_configure(fill="disabled")).grid(row=row, column=column, padx=10, pady=2)
553 | column += 1
554 |
555 | row += 1
556 | ctk.CTkFrame(master=frame ,height=2, width=1000, fg_color=("#EEEEEE", "#202020")).grid(row=row, columnspan=9)
557 | row += 1
558 | ctk.CTkLabel(text_color=("black", "white"), master=frame, text="Point Hightlight Color : ").grid(row=row, column=1)
559 | column = 2
560 | ctk.CTkButton(master=frame, text="{}".format("#FF0000"), width=90, height=30, command=lambda:line_configure(fill_color="#FF0000")).grid(row=row, column=column, padx=10, pady=2)
561 | column += 1
562 | ctk.CTkButton(master=frame, text="{}".format("00FF00"), width=90, height=30, command=lambda:line_configure(fill_color="#00FF00")).grid(row=row, column=column, padx=10, pady=2)
563 | column += 1
564 | ctk.CTkButton(master=frame, text="{}".format("#0000FF"), width=90, height=30, command=lambda:line_configure(fill_color="#0000FF")).grid(row=row, column=column, padx=10, pady=2)
565 | column += 1
566 | ctk.CTkButton(master=frame, text="{}".format("#FF00FF"), width=90, height=30, command=lambda:line_configure(fill_color="#FF00FF")).grid(row=row, column=column, padx=10, pady=2)
567 | column += 1
568 | ctk.CTkButton(master=frame, text="{}".format("#00FFFF"), width=90, height=30, command=lambda:line_configure(fill_color="#00FFFF")).grid(row=row, column=column, padx=10, pady=2)
569 |
570 |
571 | root.mainloop()
--------------------------------------------------------------------------------
/documentation/DOCUMENTATION_en.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [](DOCUMENTATION_zh.md)
4 |
5 |
6 |
7 | ---
8 |
9 |
10 |
11 |
**Usage Guide** |
**Examples** |
**Parameter Explanation** |
**Whats New ?**
12 |
13 | ### Importing & Installation
14 | * Installation
15 | ```
16 | pip install ctkchart
17 | ```
18 |
19 | * Importing
20 | ``` python
21 | import ctkchart
22 | ```
23 | ---
24 |
25 |
26 | ### Parameter Overview
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ---
39 |
40 | ### To display data using ctkchart you need to do 3 main tasks
41 | 1.
**Creating a Line Chart**
42 | 2.
**Creating a Line**
43 | 3.
**Display of data**
44 |
45 | ---
46 |
47 |
48 |
49 | ## 1 . Creating a LineChart
50 |
**Creating a Line** |
**Display of data**
51 |
52 | ``` python
53 | linechart = ctkchart.CTkLineChart()
54 | ```
55 |
56 | ### Parameters
57 |
58 | | Parameter | Required / Optional | Description | Types | Example Value(s) |
59 | |-------------------------------------------------|---------------------|--------------------------------------------|---------------------------------|-------------------------------------|
60 | | master | ***Required*** | Master Widget for LineChart | ``widget`` | widget |
61 | | [y_axis_values](#x_y_axis_values) | ***Required*** | Minimum and maximum values for y-axis | ``tuple[int \| float]`` | (-1000, 1000), ... |
62 | | [x_axis_values](#x_y_axis_values) | ***Required*** | Values for x-axis | ``tuple[any]`` | (1, 2, 3, 4, 5), ... |
63 | | width | ***Optional*** | Width of the chart | ``int`` | 300, ... |
64 | | height | ***Optional*** | Height of the chart | ``int`` | 100, ... |
65 | | [axis_size](#parameter_img) | ***Optional*** | Size of the axis | ``int`` | 1<= |
66 | | [axis_color](#parameter_img) | ***Optional*** | Color of the axis | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
67 | | [bg_color](#parameter_img) | ***Optional*** | Background color of the chart | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
68 | | [fg_color](#parameter_img) | ***Optional*** | Foreground color of the chart | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
69 | | [data_font_style](#x_y_data) | ***Optional*** | Font style for data labels | ``tuple[str, int, str]`` | ("arial", 9, "bold"), ... |
70 | | [axis_font_style](#x_y_font_style) | ***Optional*** | Font style for axis labels | ``tuple[str, int, str]`` | ("arial", 8, "normal"), ... |
71 | | [x_axis_data](#x_y_data) | ***Optional*** | Data label for x-axis | ``str`` | "X", ... |
72 | | [y_axis_data](#x_y_data) | ***Optional*** | Value for y-axi data label | ``any`` | "Y", ... |
73 | | [x_axis_data_font_color](#x_y_data) | ***Optional*** | Font color for x-axis data label | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
74 | | [y_axis_data_font_color](#x_y_data) | ***Optional*** | Font color for y-axis data label | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
75 | | [x_axis_data_position](#data_position) | ***Optional*** | Position of x-axis data label | ``str`` ("top", "side") | "top" |
76 | | [y_axis_data_position](#data_position) | ***Optional*** | Position of y-axis data label | ``str`` ("top", "side") | "top" |
77 | | [x_axis_section_count](#x_y_section) | ***Optional*** | Number of sections on the x-axis | ``int`` | 0<= |
78 | | [y_axis_section_count](#x_y_section) | ***Optional*** | Number of sections on the y-axis | ``int`` | 0<= |
79 | | [x_axis_label_count](#x_y_label_count) | ***Optional*** | Number of x-axis labels | ``int`` | 0<= |
80 | | [y_axis_label_count](#x_y_label_count) | ***Optional*** | Number of y-axis labels | ``int`` | 1<= |
81 | | [x_axis_font_color](#x_y_font_style) | ***Optional*** | Font color for x-axis labels | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
82 | | [y_axis_font_color](#x_y_font_style) | ***Optional*** | Font color for y-axis labels | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
83 | | [x_axis_section_style](#x_y_section_style) | ***Optional*** | Style of sections on the x-axis | ``str`` ("normal", "dashed") | "normal" |
84 | | [y_axis_section_style](#x_y_section_style) | ***Optional*** | Style of sections on the y-axis | ``str`` ("normal", "dashed") | "normal" |
85 | | [x_axis_section_style_type](#x_y_section_style) | ***Optional*** | Style type for sections on the x-axis | ``tuple[int, int]`` | (100, 50), ... |
86 | | [y_axis_section_style_type](#x_y_section_style) | ***Optional*** | Style type for sections on the y-axis | ``tuple[int, int]`` | (100, 50) |
87 | | [x_axis_section_color](#x_y_section) | ***Optional*** | Color of sections on the x-axis | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
88 | | [y_axis_section_color](#x_y_section) | ***Optional*** | Color of sections on the y-axis | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
89 | | [y_axis_precision](#y_precision) | ***Optional*** | Precision for y-axis values | ``int`` | 0<= |
90 | | [x_axis_display_values_indices](#indices_view) | ***Optional*** | Indices of values to display on the x-axis | ``tuple[int, ...]`` | (0, 1, 2, 3, 4, 5), ... |
91 | | [x_axis_point_spacing](#x_axis_point_spacing) | ***Optional*** | Width of lines | ``int`` \| ``str`` "auto" | "auto"
1<= |
92 | | [x_space](#parameter_img) | ***Optional*** | Space between x-axis and chart area | ``int`` | 0<= |
93 | | [y_space](#parameter_img) | ***Optional*** | Space between y-axis and chart area | ``int`` | 0<= |
94 | | pointer_state | ***Optional*** | State of the pointer | ``str`` ("enabled", "disabled") | "disabled" |
95 | | pointing_callback_function | ***Optional*** | Callback function for pointer | ``callable`` | function(*args)
function(x, y) |
96 | | pointer_color | ***Optional*** | Color of the pointer | ``tuple[str, str]`` \| ``str`` | ("#FF0000", "#00FF00"), ... |
97 | | pointing_values_precision | ***Optional*** | Precision for pointing values | ``int`` | 0<= |
98 | | pointer_lock | ***Optional*** | State of pointer lock | ``str`` ("enabled", "disabled") | "enabled" |
99 | | pointer_size | ***Optional*** | Size of the pointer | ``int`` | 1<= |
100 |
101 |
102 | ---
103 |
104 | ### Methods
105 |
106 | | Method | Description | Supported / Required Parameters | Return Type |
107 | |----------------------------|------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|-------------|
108 | | configure | Change LineChart attributes | All attributes except for master | ``None`` |
109 | | [show_data](#display-data) | Display data | data: ``list``
line: ``ctkchart.CTkLine`` | ``None`` |
110 | | place | Place LineChart | x: ``int``
y: ``int``
rely: ``float or int``
relx: ``float or int``
anchor: ``str`` | ``None`` |
111 | | pack | Pack LineChart | pady: ``int``
padx: ``int``
before: ``widget``
after: ``widget``
side: ``str``
anchor: ``str`` | ``None`` |
112 | | grid | Grid LineChart | column: ``int``
columnspan: ``int``
padx: ``int``
pady: ``int``
row: ``int``
rowspan: ``int``
sticky: ``str`` | ``None`` |
113 | | place_forget | Place forget the chart | - | ``None`` |
114 | | pack_forget | Pack forget the chart | - | ``None`` |
115 | | grid_forget | Grid forget the chart | - | ``None`` |
116 | | set_lines_visibility | Change the visibility of all the lines | state: ``bool`` | ``None`` |
117 | | set_line_visibility | Change the visibility of a specific line | line: ``ctkchart.CTkLine``
state: ``bool`` | ``None`` |
118 | | get_line_visibility | Get the visibility of a specific line | line: ``ctkchart.CTkLine`` | ``bool`` |
119 | | reset | Reset line chart | - | ``None`` |
120 | | cget | Get the value of the specified parameter | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
121 | | place_info | Get info about place | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
122 | | pack_info | Get info about pack | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
123 | | grid_info | Get info about grid | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
124 | | get_line_area | Get the are of specific line | line: `ctkchart.CTkLine` | ``float`` |
125 | | get_lines_area | Get the are of all lines | - | ``float`` |
126 | | destroy | Destroy the chart | - | ``None`` |
127 | | clear_data | Clears the data for all lines within the chart, ensuring that only the most recent visible data points are retained. If the total data points exceed the maximum visible points, the older data is removed from each line's data. This method ensures that the chart displays only the relevant portion of data based on the maximum visible range. | - | ``None`` |
128 | | get_lines_data | Retrieves data points for all lines within a specified range with an optional step value. | start: `int`
end: `int`
step: `int` | `Dict[ctkchart.CTkLine, Tuple[int]]` |
129 | get_line_data | Retrieves data points for a specific line within a specified range and step. | line: `ctkchart.CTkLine`
start: `int`
end: `int`
step: `int` | `Tuple[int \| float]` |
130 | | get_x_axis_visible_point_count | Retrieves the maximum number of data points that can be visible along the X-axis. | - | `int` |
131 | | get_lines_visible_data | Retrieves currently visible data points for all lines based on the maximum data length and visible points. | - | `Dict[ctkchart.CTkLine, Tuple[int \| float]]` |
132 | | get_line_visible_data | Retrieves currently visible data points for a specific line. | line: `ctkchart.CTkLine` | `Tuple[int \| float]` |
133 |
134 |
135 |
136 | ---
137 |
138 |
139 |
140 | ## 2 . Creating a Line
141 |
142 |
**Creating a LineChart** |
**Display of data**
143 |
144 | ``` python
145 | line = ctkchart.CTkLine()
146 | ```
147 |
148 | ### Parameters
149 |
150 | | Parameter Name | Required / Optional | Description | Types | Example Value(s) |
151 | |-------------------------------------------|---------------------|--------------------------------|----------------------------------------|------------------|
152 | | master | Required | Master of the line | ``ctkchart.CTkLine`` | LineChart obj |
153 | | [color](#line_color_size) | Optional | Color of the line | ``tuple[str, str]`` \| ``str`` | "#768df1" |
154 | | [size](#line_color_size) | Optional | Size of the line | ``int`` | 1<= |
155 | | [style](#line_style) | Optional | Style of the line | ``str`` ("normal", "dashed", "dotted") | "normal" |
156 | | [style_type](#line_style_type) | Optional | Style type for the line | ``tuple[int, int]`` | (10, 5),... |
157 | | [point_highlight](#point_highlight) | Optional | State of point highlighting | ``str`` ("enabled", "disabled") | "disabled" |
158 | | [point_highlight_size](#point_highlight) | Optional | Size of the highlighted point | ``int`` | 1<= |
159 | | [point_highlight_color](#point_highlight) | Optional | Color of the highlighted point | ``tuple[str, str]`` \| ``str`` | "#768df1" |
160 | | [fill](#fill) | Optional | State of filling | ``str`` ("enabled", "disabled") | "disabled" |
161 | | [fill_color](#fill) | Optional | Color of the fill | ``tuple[str, str]`` \| ``str`` | "#5d6db6" |
162 |
163 |
164 | ---
165 |
166 | ### Methods
167 |
168 | | Method | Description | Supported Parameters | Return Type |
169 | |----------------|------------------------------------------|--------------------------------------------|-------------|
170 | | configure | Change LineChart attributes | All attributes except for master | ``None`` |
171 | | cget | Get the value of the specified parameter | attribute_name: ``str`` \| "\_\_all\_\_" | ``any`` |
172 | | reset | reset line object | - | ``None`` |
173 | | set_visible | change the visibility of the line | state: ``bool`` | ``None`` |
174 | | get_visibility | get the visibility of the line | - | ``bool`` |
175 | | clear_data | Clears the data for a specific line, ensuring that only the most recent visible data points are retained. If the line's data exceeds the maximum visible points, the older data is trimmed. This method allows each line to independently clean its data, ensuring it remains within the visible range. | - | ``None`` |
176 | | destroy | Destroy the line | - | ``None`` |
177 | | get_data | Retrieves data points from a specified range with an optional step value. If no parameters are given, it returns all available data. | start: `int`
end: `int`
step: `int` | `Tuple[int \| float]` |
178 | | get_current_visible_data | Returns the currently visible data points based on the maximum data length across all lines and the maximum number of visible points. | - | `Tuple[int \| float]` |
179 | | get_x_axis_visible_point_count | Retrieves the maximum number of data points that can be visible along the X-axis. | - | `int` |
180 |
181 |
182 |
183 | ---
184 |
185 |
186 |
187 | ## 3 . Display of Data
188 |
189 |
**Creating a LineChart** |
**Creating a Line**
190 |
191 | ``` python
192 | import tkinter as tk
193 | import ctkchart
194 | import random
195 |
196 | #root
197 | root = tk.Tk()
198 | root.configure(bg="#151515")
199 |
200 | #creating a chart
201 | chart = ctkchart.CTkLineChart(
202 | master=root,
203 | x_axis_values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
204 | y_axis_values = (-100,100)
205 | )
206 | chart.pack()
207 |
208 | #creating a line
209 | line = ctkchart.CTkLine(master=chart)
210 |
211 | data = [x for x in range(-100,101)] #values -100 to 100
212 | #dipslay data (random)
213 | def loop():
214 | chart.show_data(line=line, data=random.choices(data, k=1))
215 | root.after(500, loop)
216 | loop()
217 |
218 | root.mainloop()
219 | ```
220 |
221 |
222 |
223 | https://github.com/Thisal-D/tkchart/assets/93121062/64440c23-63e6-4093-b027-21b00a6f5518
224 |
225 |
226 |
227 | ---
228 |
229 |
230 |
231 |
232 |
233 |
234 |
**Back to the Top** |
**Usage Guide** |
**Examples** |
**Whats New ?**
235 |
236 | ## Parameter Explanation
237 |
238 |
239 |
240 | ### CTkLineChart
241 |
242 | - #### y_axis_values
243 | y_axis_values is a tuple that containing two numeric values for the y-axis. The first value (index 0) represents the starting value of the y-axis, and the second value (index 1) represents the end value of the y-axis. This tuple defines the range of values displayed along the y-axis on chart.
244 |
245 | - #### x_axis_values
246 | x_axis_values is a collection of values that can include any data type. These values are assigned to the x-axis, starting from index 0 and continuing to the last index of the x_axis_values tuple. Each value in the tuple corresponds to a point along the x-axis in chart.
247 |
248 |
249 |
250 |
251 |
252 |
253 | ``` python
254 | chart = ctkchart.CTkLineChart(
255 | master=any_widget
256 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
257 | y_axis_values=(-100, 100)
258 | )
259 | ```
260 | ---
261 |
262 |
263 |
264 |
265 | - #### x_axis_data
266 | refers to the value type displayed in the x-axis of a chart.
267 | **Note: "X" is the default value.**
268 |
269 | - #### y_axis_data
270 | refers to the value type displayed in the y-axis of a chart.
271 | **Note: "Y" is the default value.**
272 |
273 | - #### x_axis_data_font_color
274 | refers to the font color applied to the label representing the data type on x-axis of a chart.
275 |
276 | - #### y_axis_data_font_color
277 | refers to the font color applied to the label representing the data type on y-axis of a chart.
278 |
279 | - #### data_font_style
280 | refers to the font style applied to the labels representing the data types on both the x-axis and y-axis of a chart.
281 |
282 |
283 |
284 |
285 |
286 |
287 | ``` python
288 | chart = ctkchart.CTkLineChart(
289 | master=any_widget,
290 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
291 | y_axis_values=(-100, 100),
292 | y_axis_data="Y data" ,
293 | x_axis_data="X data",
294 | x_axis_data_font_color="#ff0000",
295 | y_axis_data_font_color="#00ff00",
296 | data_font_style=("arial", 15, "underline")
297 | )
298 | ```
299 |
300 | ---
301 |
302 |
303 |
304 |
305 |
306 | - #### x_axis_label_count
307 | When you have a set of x-axis labels, such as years from 2018 to 2025, normally all these labels are shown. But sometimes you might want to show only a few of them for better clarity.
308 | For instance, if you set the x_axis_label_count to 4, it means you want to display only 4 labels instead of all 8. So, the chart will automatically skip some labels to fit your specified count.
309 | **Note: len(
x_axis_values ) is the default value.**
310 | In other words, adjusting the x_axis_label_count allows you to control how many labels appear on the x-axis, making your visualization cleaner and easier to understand.
311 |
312 | - **if there are 9 labels you can limit it to : 3, 1, 0.**
313 | - **if there are 20 labels you can limit it to : 10, 5, 4, 2, 1, 0.**
314 | - **if there are 15 labels you can limit it to : 5, 3, 1, 0.**
315 |
316 | ##### In some cases, using the x_axis_label_count parameter might not be sufficient for your needs. In such situations, you can utilize the
x_axis_display_values_indices parameter to precisely control which values are displayed on the x-axis.
317 |
318 | - #### y_axis_label_count
319 | By default, if you set the y-axis values to range from -100 to 100, only the extreme values (-100 and 100) will be displayed on the y-axis. However, you have the option to adjust the number of labels displayed using the y_axis_label_count parameter.
320 | For example, if you set y_axis_label_count to 3, the system will divide the y-axis range (-100 to 100) into equal intervals and display labels at those intervals. So, for this case, with a label count of 3, you might see labels at -100, 0, and 100.
321 | In summary, adjusting the y_axis_label_count parameter allows you to control the number of labels displayed on the y-axis, providing flexibility in customizing the visualization based on your preferences and requirements.
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 | ``` python
330 | chart = ctkchart.CTkLineChart(
331 | master=any_widget,
332 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
333 | y_axis_values=(-100, 100),
334 | x_axis_label_count=4,
335 | y_axis_label_count=10,
336 | )
337 | ```
338 |
339 | ---
340 |
341 |
342 |
343 |
344 |
345 | - #### x_axis_display_values_indices
346 |
347 | Let's say you have a set of x-axis values representing years from 2018 to 2025: (2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025). Normally, all these values would be displayed on the x-axis.
348 | However, there might be cases where you only want to display specific years rather than all of them. In such situations, you can use the x_axis_display_values_indices parameter to control which values are shown on the x-axis.
349 | For example, if you only want to display the years 2019, 2022, and 2025, you can specify their indices in the x_axis_display_values_indices parameter. So, if the index of 2919 is 1, 2022 is 4, and 2025 is 7 (assuming 0-based indexing), you would set x_axis_display_values_indices to (1, 4, 7).
350 | This way, by setting the indices of the values you want to display, you have precise control over which values appear on the x-axis in your visualization, allowing you to tailor it according to your specific requirements.
351 |
352 |
353 |
354 |
355 |
356 |
357 | ``` python
358 | chart = ctkchart.CTkLineChart(
359 | master=any_widget,
360 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
361 | y_axis_values=(-100, 100),
362 | x_axis_display_values_indices=(1, 4, 7)
363 | )
364 | ```
365 |
366 | ---
367 |
368 |
369 |
370 |
371 |
372 | - #### x_axis_data_position
373 | The x_axis_data_position parameter determines the position of the x data label. It has two
374 |
375 | supported values:
376 | - "top"
377 | - "side"
378 |
379 | **Note: "top" is the default position**
380 |
381 | - #### y_axis_data_position
382 | The y_axis_data_position parameter determines the position of the x data label. It has two
383 |
384 | supported values:
385 | - "top"
386 | - "side"
387 |
388 | **Note: "top" is the default position**
389 |
390 | Choosing between "top" and "side" determines whether the data labels are placed horizontally above the data points or vertically beside them, respectively. This parameter allows you to customize the layout of your chart according to your preferences and available space.
391 |
392 |
393 |
394 |
395 |
396 |
397 | ``` python
398 | chart = ctkchart.CTkLineChart(
399 | master=any_widget,
400 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
401 | y_axis_values=(-100, 100),
402 | x_axis_data_position="side",
403 | y_axis_data_position="top"
404 | )
405 | ```
406 |
407 | ---
408 |
409 |
410 |
411 |
412 |
413 | - #### y_axis_precision
414 |
415 | The y_axis_precision parameter controls the number of decimal places displayed for the values on the y-axis.
416 | **Note: 1 is the deafault precion**
417 | For example:
418 | - If you set y_axis_precision to 0, the values on the y-axis will be displayed as whole numbers.
419 | - If you set y_axis_precision to 1, the values on the y-axis will be displayed with one decimal place.
420 | - If you set y_axis_precision to 2, the values on the y-axis will be displayed with two decimal places.
421 |
422 |
423 | And so on :
424 | - **Adjusting the y_axis_precision parameter allows you to control the level of precision for the y-axis values in your chart. This parameter is particularly useful when dealing with data that requires specific precision or when you want to improve the readability of the chart by reducing the number of decimal places displayed.**
425 |
426 |
427 |
428 |
429 |
430 |
431 | ``` python
432 | chart = ctkchart.CTkLineChart(
433 | master=any_widget,
434 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
435 | y_axis_values=(-100, 100),
436 | y_axis_label_count=12,
437 | y_axis_precision=4,
438 | )
439 | ```
440 |
441 | ---
442 |
443 |
444 |
445 |
446 |
447 | - #### axis_font_style
448 | refers to font style of the x and y axis values
449 |
450 | - #### x_axis_font_color
451 | refers to color of x axis values
452 |
453 | - #### y_axis_font_color
454 | refers to color of y axis values
455 |
456 |
457 |
458 |
459 |
460 |
461 | ``` python
462 | chart = ctkchart.CTkLineChart(
463 | master=any_widget,
464 | x_axis_values=(2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025),
465 | y_axis_values=(-100, 100),
466 | x_axis_font_color="#00FF00",
467 | y_axis_font_color="#FF0000",
468 | axis_font_style=("arial", 13, "bold")
469 | )
470 | ```
471 |
472 | ---
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 | - #### x_axis_section_count
481 | The x_axis_section_count parameter defines the number of sections or intervals into which the x-axis range will be divided in a chart.
482 | **Here's a clearer breakdown :**
483 | - Let's say you have a range of values on the x-axis, such as years from 2018 to 2025. By default, this range might be represented as a continuous line without any specific sections or intervals marked.
484 | - However, if you set x_axis_section_count to a value, such as 8, it means you want to divide this x-axis range into equally spaced sections or intervals. Each section will represent a subset of the total x-axis range.
485 | - Adjusting the x_axis_section_count parameter allows you to control the granularity of the x-axis in your chart, making it easier for viewers to interpret the data and identify trends within specific intervals.
486 |
487 |
488 |
489 | - #### y_axis_section_count
490 | The y_axis_section_count parameter defines the number of sections or intervals into which the y-axis range will be divided in a chart.
491 | **refer :
x_axis_section_count** for more...
492 |
493 | - #### x_axis_section_color
494 | refers to color of y axis sections
495 |
496 | - #### y_axis_section_color
497 | refers to color of x axis sections
498 |
499 |
500 |
501 |
502 |
503 |
504 | ``` python
505 | chart = ctkchart.CTkLineChart(
506 | master=any_widget,
507 | x_axis_section_count=8,
508 | y_axis_section_count=5,
509 | x_axis_section_color="#2C2C2C",
510 | y_axis_section_color="#2C2C2C"
511 | )
512 | ```
513 |
514 | ---
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 | - #### x_axis_section_style
523 | x_axis_section_style parameter allows you to define the visual style of the sections along the x-axis in a chart.
524 |
525 | - Supported styles:
526 | - "dashed": When you set x_axis_section_style to "dashed", the sections along the x-axis are displayed using dashed lines.
527 | - "normal": Conversely, when x_axis_section_style is set to "normal", the sections along the x-axis are displayed using solid lines.
528 |
529 | **Note: "normal" is default style.**
530 |
531 |
532 |
533 | - #### y_axis_section_style
534 | working same as x_axis_section_style,
535 | refer
x_axis_section_style for more
536 |
537 |
538 |
539 | - #### x_axis_section_style_type
540 | The x_axis_section_style_type parameter is a tuple that contains two integer values, specifying the style of the dashes used when the x_axis_section_style is set to "dashed".
541 | For example:
542 | - If you set x_axis_section_style_type to (20, 10), it means :
543 | - The width of each dash is 20 pixels.
544 | - The spacing between dashes is 10 pixels.
545 |
546 |
547 | These values determine the visual appearance of the dashed lines or markers used to represent the sections along the x-axis. Adjusting these values allows you to customize the appearance of the dashed sections according to your preferences or the requirements of your visualization.
548 |
549 |
550 |
551 | - #### y_axis_section_style_type
552 | working same as x_axis_section_style_type,
553 | refer
x_axis_section_style_type for more
554 |
555 |
556 |
557 |
558 |
559 |
560 | ``` python
561 | chart = ctkchart.CTkLineChart(
562 | master=any_widget,
563 | x_axis_section_count=8,
564 | y_axis_section_count=5,
565 | x_axis_section_style="dashed",
566 | x_axis_section_style_type=(20,10),
567 | y_axis_section_style="dashed",
568 | y_axis_section_style_type=(20,10),
569 | )
570 | ```
571 |
572 | ---
573 |
574 |
575 |
576 |
577 |
578 | - #### x_axis_point_spacing
579 | The x_axis_point_spacing parameter allows your to manually set the spacing between points on the x-axis, typically measured in pixels. However, if you do not manually set this parameter, it is automatically calculated based on the length of x_axis_values.
580 | **Note: "auto" is the default value.**
581 |
582 |
583 | - after configure specific value to x_axis_point_spacing, you can reset value by configure it as "auto" for set default value.
584 |
585 | ``` python
586 | chart.configure(x_axis_point_spacing = "auto")
587 | ```
588 |
589 |
590 |
591 |
592 |
593 |
594 | ``` python
595 | chart = ctkchart.CTkLineChart(
596 | master=any_widget,
597 | x_axis_point_spacing="auto"
598 | )
599 | ```
600 |
601 | The x_axis_point_spacing parameter is automatically calculated based on the length of the x_axis_values tuple. This means that the spacing between points on the x-axis is determined by dividing the width of the chart by the length of the x_axis_values list.
602 |
603 |
604 |
605 |
606 |
607 |
608 | When you set the x_axis_point_spacing parameter to a specific value, such as 40, it means that you have manually specified the spacing between points on the x-axis to be 40 units (e.g., pixels). In this case, the chart will use the user-defined spacing of 40 units between each point on the x-axis, regardless of the length of the x_axis_values tuple.
609 |
610 | ``` python
611 | chart = ctkchart.CTkLineChart(
612 | master=any_widget,
613 | x_axis_point_spacing=40
614 | )
615 | ```
616 |
617 | ---
618 |
619 |
620 |
621 | ### CTkLine
622 |
623 |
624 |
625 | - #### color
626 | refers to color of line.
627 |
628 | - #### size
629 | refers to size(thickness) of line.
630 | **Note: 1 is the deafault size**
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 | ``` python
639 | line = ctkchart.CTkLine(
640 | master=chart,
641 | color="#30ACC7",
642 | size=5
643 | )
644 | ```
645 |
646 |
647 |
648 |
649 |
650 | - #### style
651 | style parameter allows you to define the visual style of the line.
652 |
653 | - supported styles:
654 | - "dashed": When you set style to "dashed", the line is displayed as dashed line.
655 | - "dotted": When you set style to "dotted", the line is displayed as dotted line.
656 | - "normal": When you set style to "normal", the line is displayed as solid line.
657 |
658 | **Note: "normal" is the default style.**
659 |
660 |
661 |
662 |
663 |
664 |
665 | ``` python
666 | line = ctkchart.CTkLine(
667 | master=chart,
668 | line_style="dashed"
669 | )
670 | ```
671 |
672 | ---
673 |
674 |
675 |
676 |
677 |
678 | - #### style_type
679 | The style_type parameter is a tuple that contains two integer values, specifying the style of the dashes and dots used when the style is set to "dashed" or "dotted".
680 |
681 | For example:
682 | - If you set style_type to (20, 10), it means:
683 | - The width of each dash or size of each dot is 20 pixels.
684 | - The spacing between dashes or dots is 10 pixels.
685 |
686 | **Note: In the "dotted" style, the size parameter is irrelevant as the dots are of fixed size determined by the style_type tuple.**
687 | **Note: In the "normal" style, the style_type parameter is do nothing.**
688 |
689 |
690 |
691 |
692 |
693 |
694 | ``` python
695 | line = ctkchart.CTkLine(
696 | master=chart,
697 | line_style="dashed",
698 | line_style_type=(10,2)
699 | )
700 | ```
701 |
702 | ---
703 |
704 |
705 |
706 |
707 |
708 | - #### point_highlight
709 | The point_highlight parameter is used to control point highlight, enabling or disabling it.
710 |
711 | - Supported values:
712 | - "enabled": Enable point highlight.
713 | - "disabled": Disable point highlight.
714 |
715 | - #### point_highlight_size
716 | The point_highlight_size is used to set size of the highlight.
717 |
718 | - #### point_highlight_color
719 | The point_highlight_color used to control color of highlight.
720 |
721 |
722 |
723 |
724 |
725 |
726 | ``` python
727 | line = ctkchart.CTkLine(
728 | master=chart,
729 | point_highlight="enabled",
730 | point_highlight_color="#80CCFF",
731 | point_highlight_size=8
732 | )
733 | ```
734 |
735 | ---
736 |
737 |
738 |
739 |
740 |
741 | - #### fill
742 | The fill parameter is utilized to control whether line fill is enabled or disabled.
743 |
744 | - Supported Values:
745 | - "enabled": Enable line fill.
746 | - "disabled": Disable line fill.
747 |
748 | - #### fill_color
749 | The fill_color parameter is used to specify the color for the fill.
750 |
751 |
752 |
753 |
754 |
755 |
756 | ``` python
757 | line = ctkchart.CTkLine(
758 | master=chart,
759 | fill="enabled",
760 | fill_color="#5D6DB6"
761 | )
762 | ```
763 |
764 | ---
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 | ## Dynamic Color Change
773 |
774 | ***For every parameter that involves color in ctkchart, you can provide either***:
775 |
776 | - A single string representing the color.
777 | - A tuple of two strings where the first string represents the color for the light theme and the second string represents the color for the dark theme.
778 |
779 |
780 |
781 | ---
782 |
783 |
808 |
809 | ---
810 |
811 | ## Links
812 |
813 | **PyPi.org** :
ctkchart
814 |
815 | **GitHub.com** :
ctkchart
--------------------------------------------------------------------------------